CameronC's items/scripts (NEW: the socketSystem)

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

CameronC's items/scripts (NEW: the socketSystem)

Post by cameronC » Sun Dec 07, 2014 9:10 am

Image

---------- Ascension Item Pack ------------------------------
Github: https://github.com/camcallahan/general- ... nsion_pack

This is a small collection of items that I hope will give people some ideas on the types of unique weapons and armor that this game engine can create with mix and matching its components around. This consists of two parts.

A Party definition with some specific code in each of the party hooks. Basically, the new Party definition, whenever any of the PartyComponent hooks are ran, scan the champions equipped items (Or the entire parties equipped items, depending on the hook) and
looks for a specifically named component. This component is a script component with a function in it. The function is ran. This lets you isolate and contain items that would otherwise have abilities you would have to check for in the party definition itself. I think it's much cleaner this way, and I seemingly have it working pretty well so far (Though I haven't tested EVERY trigger yet, and I don't think an item can return false to cancel anything YET...). The best, probably, example of this is to give armor an effect that triggers onDamage or onReceiveCondition, but it is pretty useful, I think. Now, if only I can get delayedCall to trigger a Script component on a weapon or armor, things get could really cool...

The second part is the items themselves. There are only 7 right now and they were hardly balanced with anything in mind. I just wanted to create a few interesting items, some stuff with more than just raw stat bonuses as the only way to define an item (I like the concept of items that evolve over time, that change as you use them, myself -- maybe a set of weapons that 'level up' will be next). I've got some descriptions/comment in the lua files themselves, which I'll put in the CODE tags below, and links to the actual files and an album of random screenshots taken during testing at the bottom of the post.

PSA: Due to the items having embedded scripts, if you are editing the triggerOn_____ scripts for items if you save the items lua file and restart the editor, any items in the editor will have the old scripts, so just delete and re-place the item while you are testing any embedded scripts in items.

-- Summary of Items.

Code: Select all

The Collector - A sword with a secondaryAction spell that adds charges as it deals damage to enemies.

Ceremonial Daggers - A pair of Daggers with a secondary function that requires both daggers to be equipped. Each dagger reduces the EnergyRegenerationRate but also give the champion energy when they hit a monster.

Charm of the Thief - A necklace that glows when near a trap. By default, it detects mimic chests and checks for an istrap Counter component to check for arbitrary trapped entities.

Cloak of Phasing - Cloak that has a chance to adds a temporary boon to the entire part on damage.

Heavy Shield of Bashing - Shield with meleeattack and secondaryaction components.

Travelers Cloak - Cloak that counts the steps taken while worn and adds stat bonuses the longer it is equipped.

Simple Backpack - Equippable conatineritem that grants an increase in the weight the champion can carry when equipped.

Staff of Energy Shield - Staff with secondaryaction that casts a shield on the champion that redirects all damage to his Energy pool instead. Recasting removes the effect and his energy dropping to 0 also removes the effect. If it blocks a particularly strong attack the shield has a chance to shatter as well.

Gift from Elsewhere - A bag that onInit runs a script to populate itself with various potions.
---------- socketSystem ------------------------------

The socketSystem is a simple setup that lets champions discover magical gems that can be inserted into sockets on their equipment and modify their attributes.

The basics: There is a base_object that the gems are based off of with an onUseItem hook that checks if the gem is in a champions hand and, if it is, what item is in the champions other hand. That item is then passed to a Script component inside the gem item. The script then, depending on the purpose of the gem, modifies the item being held (Or maybe it doesn't, because the champion is holding a sword and this gem only modifies shields, for example).

The system is now entirely item based and self contained. There is no massive gem check function in your dungeon.
You import the base item file and then, after that, import any gem files you want included.
If someone else ever makes a set of socketable gems, you simple put their definition file in your scripts folder and import it. Very simple.

Below is a more in depth write up on what it currently does now and a description of the 64 gems included in this current release.

Most Recent Code:
Mediafire zip: http://www.mediafire.com/download/c2vxz ... 1-4-15.zip
Github link: https://github.com/camcallahan/log2-socketSystem


Installation instructions:
SpoilerShow
1. Get the newest code from above.

2. Copy the main folders into your mod_assets folder for the dungeon (Do NOT overwrite init.lua, as you will want to just add these import lines to your file instead of losing anything you've added to yours).

The import lines that go into your init.lua are these:

Code: Select all

-- Cameron Callahan's SocketSystem Base Items
import "mod_assets/scripts/socketSystem/socketBaseItems.lua"
--[[ LordYig's Gem Collection for LOG1 (definitions for GEMS converted by Cameron for LOG2)
Alcoves in this pack have not been converted for use. Download LordYig's 
original LOG1 asset pack here: http://www.nexusmods.com/grimrock/mods/177/
--]]
import "mod_assets/scripts/socketSystem/alcoves_and_gems_collection.lua"
-- Cameron Callahan's SocketSystem Gem Sets
import "mod_assets/scripts/socketSystem/socketElementGems.lua"
import "mod_assets/scripts/socketSystem/socketAbilityGems.lua"
import "mod_assets/scripts/socketSystem/socketPassiveGems.lua"
import "mod_assets/scripts/socketSystem/socketSkullGems.lua"
socketBaseItems.lua MUST be imported before the socketSystem gem set files, as they all grab some base code from items in that first file.

Optionally, if you want to have any item have sockets added to it when you pick it up, you can add this onPickUpItem hook to your party definition in init.lua:

Code: Select all

onPickUpItem = function(self, item)
		-- General Triggers Below (Skill/Trait triggers, etc)
			local theGameEffect = item.go.item:getGameEffect()
			local beforeGE = ""
			if theGameEffect ~= nil then beforeGE = "\n" end
			if theGameEffect == nil then theGameEffect = "" end
			beforeGE = theGameEffect .. beforeGE
			if item.go.item:hasTrait("shield") and not item.go:getComponent("sockets") then
				local shieldSockets = math.random(1, 2)
				item.go:createComponent("Counter", "sockets")
				item.go.sockets:setValue(shieldSockets)
				item.go:createComponent("Counter", "gemcount")
				item.go.gemcount:setValue(shieldSockets)
				item.go.item:setGameEffect(beforeGE.."- Free Sockets ("..tostring(item.go.gemcount:getValue()).."/"..tostring(item.go.sockets:getValue())..").")
			elseif item.go.item:hasTrait("chest_armor") and not item.go:getComponent("sockets") then
				local chestSockets = math.random(2, 4)
				item.go:createComponent("Counter", "sockets")
				item.go.sockets:setValue(chestSockets)
				item.go:createComponent("Counter", "gemcount")
				item.go.gemcount:setValue(chestSockets)
				item.go.item:setGameEffect(beforeGE.."- Free Sockets ("..tostring(item.go.gemcount:getValue()).."/"..tostring(item.go.sockets:getValue())..").") 
			elseif (item.go:getComponent("meleeattack") or item.go:getComponent("rangedattack") or item.go:getComponent("firearmattack")) and not item.go:getComponent("sockets") then
				if item.go.item:hasTrait("two_handed") then
					local weaponSockets = math.random(2, 4)
					item.go:createComponent("Counter", "sockets")
					item.go.sockets:setValue(weaponSockets)
					item.go:createComponent("Counter", "gemcount")
					item.go.gemcount:setValue(weaponSockets)
					item.go.item:setGameEffect(beforeGE.."- Free Sockets ("..tostring(item.go.gemcount:getValue()).."/"..tostring(item.go.sockets:getValue())..").")
				else
					local weaponSockets = math.random(1, 2)
					item.go:createComponent("Counter", "sockets")
					item.go.sockets:setValue(weaponSockets)
					item.go:createComponent("Counter", "gemcount")
					item.go.gemcount:setValue(weaponSockets)
					item.go.item:setGameEffect(beforeGE.."- Free Sockets ("..tostring(item.go.gemcount:getValue()).."/"..tostring(item.go.sockets:getValue())..").")
				end
			end
			return
		end,
		},
README:

Code: Select all

general-log2-assets/socketSystem
===================

A D2-style weapon/armor system that allows for gems to be placed into sockets on items to alter their abilities.

The init.lua has an onPickUpItem hook that will
add the required component to allow them to be modified. This can easily be changed to only alter items
some percentage of the time instead of always.

The gem models and GfxIndex icons are from LordYig's gem/alcove pack for Grimrock 1. I converted the gem
definition to be usable in Grimrock 2 and those models/icons/descriptions/names are used as a base for 
a lot of the gems in here. I have not gone through and converted any of the alcoves in his pack.
LordYig's Grimrock 1 pack can be found on NexusMods: http://www.nexusmods.com/grimrock/mods/177/

The converted gem definitions are included and imported in this if you want to use those as is or 
modify them into more socket gems. Filtering in the editor for itm_ should bring up all of the gems.

The order of the import lines in init.lua is important.
The socketBaseItems.lua MUST come first, as it has an item in there that others use as a base_object.

The other import lines bring in the gems by "type". There are a few types included so far.

The system works by having a base_object all the gems are based on that has an onUseItem hook that does
the various checks to determine if the gem can be used, what item is it being used on, etc. Then, the 
onUseItem function calls a Script component within the gem (passing it some information on the item
the gem will be used on) and that function is what actually alters the items. This means, chiefly, there
is no gigantic script entity to place in your dungeon anywhere. It also means that if you want to change 
the behaviour of a gem you go to the object definition of the gem and that has every piece of information
you need in one place to change or troubleshoot it. It also lets the gems be separated out across different
files. If you don't want the Skull gems then just comment out that one import line and they won't show up in
the editor and there won't be any code anywhere relating to them. It also means that if someone one makes a 
set of gems, as long as you import the base item file you don't have to do anything other than import their
gem file. Super simple, super easy.

Look at the base item and included gems on how to create your own. Basically, all the GEM needs is a Script
component named "triggers" and a function named "insertGem" that accepts the variable itemToEnchant. 
Whatever you put in that script will be ran when the gem is right clicked in a champion ahnd while holding 
another item. Return true and the gem will be used, return false and it will remain.

Current gems available:

A base set of ELEMENT gems that increase stats/provide resistances. These have a specific effect depending
what type of item they are socketed in. Weapons gain attack power and elemental damage. Shields gain 
resistances. Armor gain minor and major stat bonuses.

The SKULL gems switch and change the lower-level properties of an item, like baseDamageStat and
skill requirements. There is a skull for each of the four major stats that will change the stat
used to scale damage up (So maybe a new found hammer can be wielded fiercely by a willpower mage, for 
instance). There are also gems to converted heavy_armor requirements to light_armor, and other similar
effects.

The PASSIVE gems are similar to the ELEMENT gems but with less restrictions. They increase stats by a 
more limited amount but can be inserted into any type of item with slots. So, while a high level SAPPHIRE
will only provide willpower when put into a chest_armor, one of these willpower gems will give you the 
bonus even when put into a shield or weapon. These mostly provide stat bonuses, but there are a few other
things that they can alter as well.

ABILITY gems provide secondary actions. Currently, there is only a small pool of them. There is one for the
base Bolt-type spells for weapons and ones that provide shields with the elemental shield-type spells. There
is also one that provides the ability MUG to a dagger. This allows a champion with a dagger to shake down the
enemy and has a small chance to drop items for the party. 

To manually create an item with the ability to accept gems, the weapon/armor requires two components:

- A Counter component named "sockets", set to the max amount of gems the item can accept.
- A Counter component named "gemcount", initially set to the same value as "sockets". This is decreased
when enchanting an item and prevents gems from being used when at 0.

Currently shields, chest pieces, and non-RunePanel weapons can be enchanted. Shields are given 1-2 slots,
chest pieces are given 2-4, and weapons are given 1-2 slot each (Except weapons with the "two_handed" trait
are given 2-4 slots).

To modify an item, place one of the gems into a champion's hand along with the item to enchant in the
other hand. Right-click the gem to enchant the other item being held. The gem will vanish and print out
the effect of the gem.

If the other item being held does not have the correct components to be enchanted then it will print out
that fact and the gem will remain in the champion's hand. Similarly, if the item has no more free sockets
then the gem will have no effect and remain in hand.

To-do/Fixes needed:

- Find a better way to display the amount of free sockets in items. Currently, an item with a gameEffect 
will have it erased and replaced with the free socket count. Perhaps a simple gameEffect/description 
manager needs to be implemented so that -lines- of information can be retrieved/modified without hurting
other lines of information in the strings.
- secondaryAction spells have charges that DO work, but are not displayed when hovered over the item. Unsure
what is causing this.
- Determine if it is possible to script a sort of setPowerAttackTemplate to dynamically add the predefined 
power attacks to weapons... or at least reverse-engineer some of the more interesting ones to use.


NOTE: The gems currently have another Counter component in them named "treasureclass" that is unrelated to
the socketSystem. 
Last edited by cameronC on Sun Jan 04, 2015 10:23 pm, edited 13 times in total.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github

Grimfan
Posts: 369
Joined: Wed Jan 02, 2013 7:48 am

Re: [Items] Ascension pack v1 and self-contained party hooks

Post by Grimfan » Mon Dec 08, 2014 3:12 am

Excellent work Cameron. We need quality scripters like you around to keep this community alive and ticking. I hope to see you working on some other cool stuff in the future. :D

cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

New Items.

Post by cameronC » Sat Dec 13, 2014 9:55 pm

Thanks grimfan.

I've tidied things up and added some new items (And made the existing items nicer).

Summary of new items include:

* Staff of Energy Shield.
secondaryAction casts a spell that causes damage to the champion to be redirected to his energy. The effect ends when the spell is recast, his energy reaches 0, or sometimes when a large amount of damage is absorbed. His energy regeneration is also reduced, as without lowering that it is too strong. Potions and other energy gain still work normally.

* A simple backpack that stores items and can also be equipped in the cloak slot. The advantage to equipping the backpack is an increase is the weight you can carry. This is done via onRecomputeStats in the equipmentitem component.

* Gift From Elsewhere. A bag that onInit populates itself with some potions. Initially an idea that could be used as a levelup reward, giving some support and a small chance at a stat up potion. Currently it runs through the same script when spawned but could be tailored to give appropriate items/potions/armor depending on who is leveling up. Say, spawn it in the inventory of a mage that levels and have a small chance at giving potion_willpower and a new wand, but some enchanted arrows and a chance at a potion_dexterity if a rogue levels, etc.


github link: https://github.com/camcallahan/general- ... nsion_pack

ascension_items.lua:

Code: Select all

--[[
Ascension Items Pack
by Cameron Callahan @camcallahan
Requires the Ascension Party hooks to be in your init.lua.
A small set of items meant to show off some really neat 
things the Grimrock 2 engine can do with items. 
Summary of some of the neat things:
* Sword that has a spell secondaryAction that gains charges
as you damage enemies.
* A cloak that has a chance to invis the whole party briefly
when the wearer takes damage.
* A cloak that counts the steps you take with it on and as
you travel grants more stat bonuses.
* A set of daggers that have a secondaryAction that is 
worthless without both daggers equipped.
* That same set of daggers plays around with the concept of
energy a little bit, too, providing Energy when they hit a 
monster but also draining your energy. This sort of concept 
can certainly add some depth to having two weapon sets 
available to the champions.
* A necklace that changes colors when near a trap. Currently,
this scans the surrounding tiles onMove and looks for a couple
things: Is there a chest that is a Mimic nearby and is there 
any entity with a istrap Counter component that has a value 
greater than 0. If either is true, is swaps the gfxIndex for a 
new necklace. This currently uses some icons from Akroma's icon 
sets on the grimrock forums. At first you right-clicked it to 
scan the area, then I set up the party wide hooks and changed 
it to be a passive effect. It looking for the istrap Counter 
lets you allow it to warn the champions of booby-trapped doors 
or anything else. You could also make it do a check against the 
istrap and not activate if the Counter is above a certain number, 
so super difficult/elaborate traps won't actually trigger the 
necklace... or the necklace won't trigger against really hard 
traps unless the wearer is a Rogue, etc.
-- Akroma's icons: http://www.grimrock.net/forum/viewtopic.php?f=22&t=8058
* A shield that you can meleeattack with and has a secondaryAction.
This one is less impressive, but I think shields were an item type
that were a little plain in the game, given how dynamic the 
component setup is. This shield has a secondaryAction that knocks 
back the enemy.
* A sack-like backpack that can be equipped. The advantage of equipping
it versus just storing items in it and leaving it in your inventory
is that when equipped it increases the max_load of a character so
that they can carry more items.
* Staff of Energy Shield. When the secondaryAction is used it casts a
spell that adds a trait that triggers an onDamage party hook for the
champion and prevents any damage dealt to him and reduces the champion's
energy by the same amount. If the champion's energy reaches zero they 
lose the Shield. While protected, the champion's energyRegenerationRate 
is reduced so that it drains very slowly, though potions and other 
Energy gaining effects can still increase their Energy pool. If hit by
a particularly strong blow there is a chance for the shield to shatter.
* Gift From Elsewhere. A bag that onInit will add a random set of potions
to itself. It will always give a healing potion, sometimes a greater healing
potion. It will usually give an energy potion, though sometimes that will
be a greater energy potion. Small chance for resurrection potion and a stat
potion. Then one or two random effect/cure potions. Cannot be added to an 
enemy in the editor, as it won't run the onInit function... Can be spawned 
added to the monster with addItem(), though. Could be used as a reward when
the party levels, providing some support and occasionally a small stat boost.
--]]





defineObject{
	name = "the_collector",
	baseObject = "base_item",
	tags = { "weapon", "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/claymore.fbx",
		},
		{
			class = "Item",
			uiName = "The Collector",
			description = "Those slain by this blade are forever following it, waiting to be released.",
			gfxIndex = 401,
			gfxIndexPowerAttack = 464,
			impactSound = "impact_blade",
			weight = 4.2,
			traits = { "heavy_weapon", "two_handed", "sword", "epic" },
			secondaryAction = "poisonBolt",
		},
		{
			class = "Counter",
			name = "collection",
			value = 0,
		},
		{
			class = "MeleeAttack",
			attackPower = 35,
			accuracy = 0,
			cooldown = 5,
			damageType = "cold",
			swipe = "vertical",
			attackSound = "swipe_heavy",
			requirements = { "heavy_weapons", 5 },
			onHitMonster = function(self, monster, tside, damage, champion)
				local doDebug = false
				local currentCount = self.go.collection:getValue()
				local amountLow = (damage / 5)
				local amountHigh = (damage / 2)
				local collectedCount = math.random(amountLow, amountHigh)
				if doDebug then print("currentCount:", currentCount) end
				if doDebug then print("Low:",amountLow,"High:", amountHigh) end
				if doDebug then print("Collected:", collectedCount) end
				self.go.collection:setValue(currentCount + collectedCount)
				if doDebug then print("New Count:", self.go.collection:getValue()) end
				if self.go.collection:getValue() >= 100 then
					local currentCharges = self.go.poisonBolt:getCharges()
					if currentCharges < 3 then
						if doDebug then print("Charge added, resetting count.") end
						self.go.poisonBolt:setCharges(currentCharges + 1)
						self.go.collection:setValue(0)
						hudPrint("The Collector screams with power.")
					else
						self.go.collection:setValue(0)
					end
				end
			end,
		},
		{
			class = "CastSpell",
			name = "poisonBolt",
			uiName = "Poison Bolt",
			cooldown = 5,
			spell = "poison_bolt",
			energyCost = 40,
			power = 30,
			charges = 2,
			requirements = { "concentration", 2 },
		},
	},
}

defineObject{
	name = "ceremonial_dagger_of_flesh",
	baseObject = "base_item",
	tags = { "weapon", "ascension_items" },
	components = {
		{
			class = "Model",
			model = "assets/models/items/backbiter.fbx",
		},
		{
			class = "Item",
			uiName = "Ceremonial Dagger of Flesh",
			description = "One of two daggers used centuries ago in the creation of a massive army of flesh golems.",
			gfxIndex = 228,
			gfxIndexPowerAttack = 202,
			impactSound = "impact_blade",
			weight = 2.4,
			secondaryAction = "sacrifice",
			traits = { "light_weapon", "dagger" },
			gameEffect = "Drains energy. Successful attacks replenish energy.",
		},
		{
			class = "MeleeAttack",
			attackPower = 25,
			cooldown = 1.2,
			swipe = "vertical",
			attackSound = "swipe_light",
			onHitMonster = function(self, monster, side, dmg, champion)
				champion:regainEnergy(14)
			end,
		},
		{
			class = "MeleeAttack",
			name = "sacrifice",
			uiName = "Sacrifice",
			attackPower = 30,
			accuracy = 20,
			cooldown = 4.5,
			energyCost = 45,
			swipe = "vertical",
			attackSound = "swipe_light",
			requirements = { "light_weapons", 3 },
			onHitMonster = function(self, monster, side, dmg, champion)
				dmg = 0
				local weaponItem = champion:getItem(ItemSlot.Weapon)
				local otherItem = champion:getItem(ItemSlot.OffHand)
				if weaponItem == nil then return end
				if otherItem == nil then return end
				if otherItem.go.name == "ceremonial_dagger_of_rot" or weaponItem.go.name == "ceremonial_dagger_of_rot" then
					for i = 1,4 do
						local stabbyDamage = rollDamage(45, "vitality")
						local monsterHealth = monster.go.monster:getHealth()
						local luckMod = 0
						if party:getComponent("luck") then
							luckMod = party.luck:getValue()
						end
						if luckMod == nil then luckMod = 0 end
						-- If you add a Counter component named "luck"
						-- to your Party, you can use that as a general
						-- counter to modify the chance that a special
						-- action happens. If the party is lucky, it
						-- means sacrifices happen a little more.
						if (math.random(1, 100) + luckMod) > 95 then
							stabbyDamage = stabbyDamage + 500 
							hudPrint("A SACRIFICE IS MADE.")
							local baseHealth = self.go.equipmentitem:getHealth()
							if baseHealth == nil then baseHealth = 0 end
							self.go.equipmentitem:setHealth(baseHealth + 15)
						end
						monster.go.monster:setHealth( monsterHealth - stabbyDamage )
						monster.go.monster:showDamageText(tostring(stabbyDamage), "FF0000")
						if monster.go.monster:getHealth() <= 0 then monster.go.monster:die() end
					end
				end
			end,
		},
		{
			class = "EquipmentItem",
			name = "equipmentitem",
			slot = ItemSlot.Weapon,
			energyRegenerationRate = -95,
		},
		{
			class = "Light",
			name = "light",
			range = 1,
			brightness = 4,
			color = vec(0,0,7),
		}
	},
}
defineObject{
	name = "ceremonial_dagger_of_rot",
	baseObject = "base_item",
	tags = { "weapon", "ascension_items" },
	components = {
		{
			class = "Model",
			model = "assets/models/items/backbiter.fbx",
		},
		{
			class = "Item",
			uiName = "Ceremonial Dagger of Rot",
			description = "One of two daggers used centuries ago in the creation of a massive army of flesh golems.",
			gfxIndex = 228,
			gfxIndexPowerAttack = 202,
			impactSound = "impact_blade",
			weight = 2.4,
			secondaryAction = "sacrifice",
			traits = { "light_weapon", "dagger" },
			gameEffect = "Drains energy. Successful attacks replenish energy.",
		},
		{
			class = "MeleeAttack",
			attackPower = 25,
			cooldown = 1.2,
			swipe = "vertical",
			attackSound = "swipe_light",
			onHitMonster = function(self, monster, side, dmg, champion)
				champion:regainEnergy(14)
			end,
		},
		{
			class = "MeleeAttack",
			name = "sacrifice",
			uiName = "Sacrifice",
			attackPower = 0,
			accuracy = 20,
			cooldown = 4.5,
			energyCost = 45,
			swipe = "vertical",
			attackSound = "swipe_light",
			requirements = { "light_weapons", 3 },
			onHitMonster = function(self, monster, side, dmg, champion)
				dmg = 0
				local weaponItem = champion:getItem(ItemSlot.Weapon)
				local otherItem = champion:getItem(ItemSlot.OffHand)
				if weaponItem == nil then return end
				if otherItem == nil then return end
				if otherItem.go.name == "ceremonial_dagger_of_rot" or weaponItem.go.name == "ceremonial_dagger_of_rot" then
					for i = 1,4 do
						local stabbyDamage = rollDamage(45, "vitality")
						local monsterHealth = monster.go.monster:getHealth()
						local luckMod = 0
						if party:getComponent("luck") then
							luckMod = party.luck:getValue()
						end
						if luckMod == nil then luckMod = 0 end
						-- If you add a Counter component named "luck"
						-- to your Party, you can use that as a general
						-- counter to modify the chance that a special
						-- action happens. If the party is lucky, it
						-- means sacrifices happen a little more.
						if (math.random(1, 100) + luckMod) > 95 then
							stabbyDamage = stabbyDamage + 500 
							hudPrint("A SACRIFICE IS MADE.")
							local baseHealth = self.go.equipmentitem:getHealth()
							if baseHealth == nil then baseHealth = 0 end
							self.go.equipmentitem:setHealth(baseHealth + 15)
						end
						monster.go.monster:setHealth( monsterHealth - stabbyDamage )
						monster.go.monster:showDamageText(tostring(stabbyDamage), "FF0000")
						if monster.go.monster:getHealth() <= 0 then monster.go.monster:die() end
					end
				end
			end,
		},
		{
			class = "EquipmentItem",
			name = "equipmentitem",
			slot = ItemSlot.Weapon,
			energyRegenerationRate = -95,
		},
		{
			class = "Light",
			name = "light",
			range = 1,
			brightness = 4,
			color = vec(7,0,0),
		}
	},
}


defineObject{
	name = "charm_of_the_thief",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/spirit_mirror_pendant.fbx",
		},
		{
			class = "Item",
			uiName = "The Charm of the Thief",
			description = "A good luck charm crafted by an expert thief.",
			-- Requires Akroma's icons from grimrock forums
			-- http://www.grimrock.net/forum/viewtopic.php?f=22&t=8058
			-- If those are in your mod_assets/textures folder then
			-- uncomment the lines below and in the un/equip and onMove
			-- sections below and comment out the gfxIndex = 74/26 lines.
			-- gfxAtlas = "mod_assets/textures/akroma_icons2.dds",
			-- gfxIndex = 25,
			gfxIndex = 74,
			weight = 0.2,
			gameEffect = "Senses danger.",
			traits = { "necklace" },
			onUnequipItem = function(self, champion, slot)
				--self.go.item:setGfxIndex(25)
				self.go.item:setGfxIndex(74)
			end,
			onEquipItem = function(self, champion, slot)
				--self.go.item:setGfxIndex(25)
				self.go.item:setGfxIndex(74)
			end,
		},
		{
			class = "EquipmentItem",
			evasion = 10,
		},
		{
			class = "Script",
			name = "triggerOnMove",
			source = [[function performAction(dummyself, direction)
				local foundTrap = false
				for xx = party.x - 1, party.x + 1 do
				for yy = party.y - 1, party.y + 1 do
				for i in party.map:entitiesAt(xx, yy) do
					if i:getComponent("istrap") then
					if i.istrap:getValue() > 0 then foundTrap = true end
					end
					if i:getComponent("chest") then
					if i.chest:getMimic() then foundTrap = true end
					end
				end
				end
			end
			if foundTrap then 
				--self.go.item:setGfxIndex(23)
				self.go.item:setGfxIndex(26)
			else
				--self.go.item:setGfxIndex(25)
				self.go.item:setGfxIndex(74)
			end
			end
			]]
		},
	},
}

defineObject{
	name = "cloak_of_phasing",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/diviner_clothes.fbx",
		},
		{
			class = "Item",
			uiName = "Cloak of Phasing",
			description = "A cloak that exists in this world and elsewhere simultaneously.",
			gfxIndex = 167,
			weight = 0.6,
			traits = { "cloak" },
		},
		{
			class = "Script",
			name = "triggerOnDamage",
			source = [[
				function performAction(self, champion, damage, damageType)
					local chanceToPhase = 35
					if math.random(1, 100) <= chanceToPhase then
					for i = 1, 4 do
					party.party:getChampion(i):setConditionValue("invisibility", 5)
					end
					end
				end
			]]
		},
	},
}
defineObject{
	name = "heavy_shield_of_bashing",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/heavy_shield.fbx",
		},
		{
			class = "Item",
			uiName = "Heavy Shield of Bashing",
			description = "It's bashing time!",
			gfxIndex = 15,
			gfxIndexPowerAttack = 15,
			impactSound = "impact_blunt",
			weight = 6.5,
			traits = { "shield" },
		},
		{
			class = "EquipmentItem",
			slot = "Weapon",
			protection = 10,
		},
		{
			class = "MeleeAttack",
			attackPower = 30,
			cooldown = 6,
			swipe = "vertical",
			attackSound = "swipe_heavy",
			requirements = { "heavy_weapons", 3 },
			powerAttackTemplate = "knockback",
		},
	},
}

defineObject{
	name = "travelers_cloak",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/spidersilk_cloak.fbx",
		},
		{
			class = "Item",
			uiName = "Traveler's Cloak",
			gfxIndex = 321,
			weight = 0.5,
			traits = { "cloak" },
			description = "Knowledge comes from travel and new experiences.",
		},
		{
			class = "EquipmentItem",
			evasion = 15,
			willpower = 1,
		},
		{
			class = "Counter",
			name = "steps",
			value = 0,
		},
		{
		class = "Script",
		name = "triggerOnMove",
		source = [[
			function performAction(dummyself, direction)
				local stepCount = self.go.steps:getValue() + 1
				local willpowerCount = self.go.equipmentitem:getWillpower()
				if willpowerCount == nil then willpowerCount = 0 end
				self.go.steps:setValue(stepCount)
				if stepCount > (100 + ((willpowerCount - 1) * 350)) then
					self.go.equipmentitem:setWillpower(willpowerCount + 1)
					self.go.steps:setValue(0)
				end
			end
			]]
		},
	},
}

defineObject{
	name = "simple_backpack",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/sack_empty.fbx",
		},
		{
			class = "Item",
			uiName = "Simple Backpack",
			gfxIndex = 82,
			gfxIndexContainer = 482,
			weight = 0.4,
			fitContainer = false,
			gameEffect = "Stores items and increases carry capacity when worn.",
			description = "A simple drawstring backpack.",
			traits = { "cloak" },
		},
		{
			class = "EquipmentItem",
			evasion = -5,
			onRecomputeStats = function(self, champion)
				if champion:getLevel() > 0 then
					champion:addStatModifier("max_load", 35)
				end
			end,
		},
		{
			class = "ContainerItem",
			name = "backpack",
			containerType = "sack",
			openSound = "container_sack_open",
			closeSound = "container_sack_close",
			onInit = function(self)
				if self:getItemCount() > 0 then
					self.go.model:setModel("assets/models/items/sack_full.fbx")
					self.go.item:setGfxIndex(81)
					self.go.item:updateBoundingBox()
				end
			end,
			onInsertItem = function(self, item)
				-- convert to full sack
				if self.go.item:getGfxIndex() == 82 then
					self.go.model:setModel("assets/models/items/sack_full.fbx")
					self.go.item:setGfxIndex(81)
					self.go.item:updateBoundingBox()
				end
			end,
			onRemoveItem = function(self, item)
				-- convert to empty sack when last item is removed
				if self:getItemCount() == 0 and self.go.item:getGfxIndex() == 81 then
					self.go.model:setModel("assets/models/items/sack_empty.fbx")
					self.go.item:setGfxIndex(82)
					self.go.item:updateBoundingBox()
				end
			end,
		},
	},
}

defineObject{ 
	name = "staff_of_energy_shield",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/shaman_staff.fbx",
		},
		{
			class = "Item",
			uiName = "Staff of Energy Shield",
			description = "A rune covered staff with a pulsating poison green gem attached to its tip. You can sense great power in it.",
			gfxIndex = 1,
			gfxIndexPowerAttack = 440,
			impactSound = "impact_blunt",
			weight = 3.3,
			secondaryAction = "energyShield",
		},
		{
			class = "RunePanel",
			requirements = { "concentration", 2 },
		},
		{
			class = "EquipmentItem",
			slot = "Weapon",
			energy = 25,
		},
		{
			class = "CastSpell",
			name = "energyShield",
			uiName = "Energy Shield",
			cooldown = 5,
			spell = "energy_shield",
			energyCost = 25,
			power = 0,
			requirements = { "concentration", 3 },
		},
	},
}

defineObject{
	name = "gift_from_elsewhere",
	baseObject = "base_item",
	tags = { "ascension_items", },
	components = {
		{
			class = "Model",
			model = "assets/models/items/sack_empty.fbx",
		},
		{
			class = "Item",
			uiName = "Gift From Elsewhere",
			gfxIndex = 82,
			gfxIndexContainer = 482,
			weight = 0.4,
			fitContainer = false,
			description = "A gift appears as if from out of thin air.",
		},
		{
			class = "Particle",
		},
		{
			class = "ContainerItem",
			name = "containeritem",
			containerType = "sack",
			openSound = "container_sack_open",
			closeSound = "container_sack_close",
			onInit = function(self)
				local potionRoll = math.random(1, 100)
				if potionRoll <= 80 then
					self.go.containeritem:addItem(spawn("potion_healing").item)
				else
					self.go.containeritem:addItem(spawn("potion_greater_healing").item)
				end
				potionRoll = math.random(1, 100)
				if potionRoll <= 30 then
					self.go.containeritem:addItem(spawn("potion_healing").item)
				elseif potionRoll >= 31 and potionRoll <= 50 then
					self.go.containeritem:addItem(spawn("potion_greater_healing").item)
				end
				potionRoll = math.random(1, 100)
				if potionRoll <= 50 then
					self.go.containeritem:addItem(spawn("potion_energy").item)
				elseif potionRoll >= 51 and potionRoll <= 70 then
					self.go.containeritem:addItem(spawn("potion_greater_energy").item)
				end
				potionRoll = math.random(1, 100)
				if potionRoll <= 20 then
					self.go.containeritem:addItem(spawn("potion_bear_form").item)
				end
				potionRoll = math.random(1, 100)
				if potionRoll <= 20 then
					self.go.containeritem:addItem(spawn("potion_resurrection").item)
					self.go.particle:setParticleSystem("power_gem_item")
				end
				potionRoll = math.random(1, 100)
				if potionRoll <= 20 then
					self.go.particle:setParticleSystem("power_gem_item")
					local whichStat = math.random(1, 4)
					if whichStat == 1 then self.go.containeritem:addItem(spawn("potion_dexterity").item) end
					if whichStat == 2 then self.go.containeritem:addItem(spawn("potion_strength").item) end
					if whichStat == 3 then self.go.containeritem:addItem(spawn("potion_vitality").item) end
					if whichStat == 4 then self.go.containeritem:addItem(spawn("potion_willpower").item) end
				end
				for i = 1, 2 do
					potionRoll = math.random(1, 7)
					if potionRoll == 1 then
						self.go.containeritem:addItem(spawn("potion_shield").item)
					elseif potionRoll == 2 then
						self.go.containeritem:addItem(spawn("potion_rage").item)
					elseif potionRoll == 3 then
						self.go.containeritem:addItem(spawn("potion_bear_form").item)
					elseif potionRoll == 4 then
						self.go.containeritem:addItem(spawn("potion_speed").item)
					elseif potionRoll == 5 then
						self.go.containeritem:addItem(spawn("potion_cure_poison").item)
					elseif potionRoll == 6 then
						self.go.containeritem:addItem(spawn("potion_cure_disease").item)
					end
				end
				if self:getItemCount() > 0 then
					self.go.model:setModel("assets/models/items/sack_full.fbx")
					self.go.item:setGfxIndex(81)
					self.go.item:updateBoundingBox()
				end
			end,
			onInsertItem = function(self, item)
				-- convert to full sack
				if self.go.item:getGfxIndex() == 82 then
					self.go.model:setModel("assets/models/items/sack_full.fbx")
					self.go.item:setGfxIndex(81)
					self.go.item:updateBoundingBox()
				end
			end,
			onRemoveItem = function(self, item)
				-- convert to empty sack when last item is removed
				if self:getItemCount() == 0 and self.go.item:getGfxIndex() == 81 then
					self.go.model:setModel("assets/models/items/sack_empty.fbx")
					self.go.item:setGfxIndex(82)
					self.go.item:updateBoundingBox()
				end
			end,
		},
	},
}


-------------------
--    TRAITS     --
-------------------


defineTrait{
	name = "energyshield",
	uiName = "Energy Shield",
	icon = 11,
	charGen = false,
	hidden = false,
	gameEffect = "Energy Shield allows damage taken to be absorbed by your Energy, depleting that instead of your Health. Running out of Energy removes this effect.",	
	description = "Creates a magical barrier surrounding the caster, absorbing damage. Particularly strong blows can shatter the barrier.",
	onRecomputeStats = function(champion, level)
		if level > 0 then
			champion:addStatModifier("energy_regeneration_rate", -110)
		end
	end,
}

-------------------
--    SPELLS     --
-------------------

defineSpell{
	name = "energy_shield",
	uiName = "Energy Shield",
	gesture = 0,
	manaCost = 50,
	onCast = function(champion, x, y, direction, elevation, skillLevel)
		if champion:hasTrait("energyshield") then
			champion:removeTrait("energyshield")
		elseif not champion:hasTrait("energyshield") then
			champion:addTrait("energyshield")
		end
	end,
	skill = "concentration",
	requirements = { "concentration", 3 },
	icon = 85,
	spellIcon = 12,
	description = "Creates a magical barrier surrounding the champion, absorbing damage. Particularly strong blows can shatter the barrier.",
}
init.lua:

Code: Select all

-- This file has been generated by Dungeon Editor 2.1.18

-- import standard assets
import "assets/scripts/standard_assets.lua"

-- import custom assets
import "mod_assets/scripts/items.lua"
import "mod_assets/scripts/monsters.lua"
import "mod_assets/scripts/objects.lua"
import "mod_assets/scripts/tiles.lua"
import "mod_assets/scripts/recipes.lua"
import "mod_assets/scripts/spells.lua"
import "mod_assets/scripts/materials.lua"
import "mod_assets/scripts/sounds.lua"

-- Cameron Callahan's Ascended Items Pack
import "mod_assets/scripts/ascension_items.lua"

--[[
Ascension Items Pack
by Cameron Callahan @camcallahan

Party Object definition that scans items in the inventory
for a specifically named Script class depending on the 
trigger hook and runs the performAction function contained
inside the items in the inventory. This lets you have fairly
self-contained items that can do things easily based off
of hooks that Items don't have built in without having a 
giant, messy set of 'if item' checks in the party.
--]]

defineObject{
   name = "party",
   baseObject = "party",
   components = {
      {
         class = "Party",  
		onCast = function(self, champion, spell)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnCast") then
					checkItem.go.triggerOnCast.performAction( champion, spell)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
			
			
			if setFalse then return false end
			return self, champion, spell
		end,
		onDamage = function(self, champion, damage, damageType)
		local setFalse = false
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnDamage") then
					checkItem.go.triggerOnDamage.performAction(self, champion, damage, damageType)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)	
			if champion:hasTrait("energyshield") then
				if damage > 100 then
					local chanceToShatter = 7
					if math.random(1, 100) < chanceToShatter then
						hudPrint("The Energy Shield protecting ".. champion:getName() .. " shatters!")
						champion:removeTrait("energyshield")
						
						champion:damage(damage, damageType)
					end
				end
				local currentEnergy = champion:getEnergy()
				champion:setEnergy(currentEnergy - damage)
				if champion:getEnergy() < 0 then
					champion:removeTrait("energyshield")
					champion:setEnergy(0)
				end
				setFalse = true
			end
			
			
			if setFalse then return false end
			return self, champion, damage, damageType
		end,
		onDie = function(self, champion)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnDie") then
					checkItem.go.triggerOnDie.performAction(self, champion)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)	
			
			if setFalse then return false end
			return self, damage
		end,
		onAttack = function(self, champion, action, slot)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnAttack") then
					checkItem.go.triggerOnAttack.performAction(self, champion, action, slot)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)	
			
			if setFalse then return false end
			return self, champion, action, slot
		end,
		onLevelUp = function(self, champion)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnLevelUp") then
					checkItem.go.triggerOnLevelUp.performAction(self, champion)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
			
			
			if setFalse then return false end
			return self, champion
		end,
		onReceiveCondition = function(self, champion, condition)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnReceiveCondition") then
					checkItem.go.triggerOnReceiveCondition.performAction(self, champion, condition)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
			
			if setFalse then return false end
			return self, champion, condition
		end,
		onPickUpItem = function(self, item)
		-- Auto Check For Item Specific Triggers below	
			for j = 1, 4 do
			for i = 1, 10 do
				local checkItem = party.party:getChampion(j):getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnPickUpItem") then
					checkItem.go.triggerOnPickUpItem.performAction(self, item)
					end
				end
			end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
		
		
			if setFalse then return false end
			return self, item
		end,
		onProjectileHit = function(self, champion, item, damage)
		-- Auto Check For Item Specific Triggers below	
			for i = 1, 10 do
				local checkItem = champion:getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnProjectileHit") then
					checkItem.go.triggerOnProjectileHit.performAction(self, champion, item, damage)
					end
				end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
		
			if setFalse then return false end
			return self, item
		end,
		onRest = function(self)
		-- Auto Check For Item Specific Triggers below	
			for j = 1, 4 do
			for i = 1, 10 do
				local checkItem = party.party:getChampion(j):getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnRest") then
					checkItem.go.triggerOnRest.performAction(self)
					end
				end
			end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
		
			if setFalse then return false end
			return self
		end,
		onWakeUp = function(self)
		-- Auto Check For Item Specific Triggers below	
			for j = 1, 4 do
			for i = 1, 10 do
				local checkItem = party.party:getChampion(j):getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnWakeUp") then
					checkItem.go.triggerOnWakeUp.performAction(self)
					end
				end
			end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
		
			if setFalse then return false end
			return self
		end,
		onTurn = function(self, direction)
		-- Auto Check For Item Specific Triggers below	
			for j = 1, 4 do
			for i = 1, 10 do
				local checkItem = party.party:getChampion(j):getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnTurn") then
					checkItem.go.triggerOnTurn.performAction(self, direction)
					end
				end
			end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
		
			if setFalse then return false end
			return self, direction
		end,
		onMove = function(self, direction)
		-- Auto Check For Item Specific Triggers below	
			for j = 1, 4 do
			for i = 1, 10 do
				local checkItem = party.party:getChampion(j):getItem(i)
				if checkItem ~= nil then
					if checkItem.go:getComponent("triggerOnMove") then
					checkItem.go.triggerOnMove.performAction(self, direction)
					end
				end
			end
			end
		-- General Triggers Below (Skill/Trait triggers, etc)
		
			if setFalse then return false end
			return self, direction
		end,
		},
		{
			class = "Counter",
			name = "luck",
			value = 0,
		},
   },
}
Last edited by cameronC on Sun Dec 14, 2014 7:36 am, edited 3 times in total.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github

User avatar
Drakkan
Posts: 1317
Joined: Mon Dec 31, 2012 12:25 am

Re: [Items] Ascension pack (new: Staff of Energy Shield+othe

Post by Drakkan » Sat Dec 13, 2014 10:22 pm

I didn´t notice this thread before, but dude - I am impressed. Really interesting ideas and items and this scripting... just wow. Hope I will see these functional is some mod !
Breath from the unpromising waters.
Eye of the Atlantis

User avatar
sapientCrow
Posts: 394
Joined: Sun Apr 22, 2012 10:57 am

Re: [Items] Ascension pack (new: Staff of Energy Shield+othe

Post by sapientCrow » Sun Dec 14, 2014 1:40 am

impressive is correct!!
thank you
this is some innovative and clean work

cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: [Items] Ascension pack (new: Staff of Energy Shield+othe

Post by cameronC » Tue Dec 16, 2014 4:59 pm

Thanks, guys. In the process of doing some armor sets with bizarre effects, and weapon mod systems.
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github

cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: CameronC's items/scripts (NEW: the socketSystem)

Post by cameronC » Fri Dec 26, 2014 2:12 am

---------- socketSystem ------------------------------

Github link:
https://github.com/camcallahan/general- ... cketSystem

The socketSystem is a simple setup that lets champions use magical gems that can be inserted into sockets on their equipment and modify their attributes. Below is a more in depth write up on what it currently does now.

Code: Select all

A D2-style weapon/armor system that allows for gems to be placed into sockets on items to alter their abilities.

Currently, it includes only a basic set of gems of varying quality, which provide different bonuses depending on the type of item they are inserted into. The init.lua has an onPickUpItem hook that will add the required component to allow them to be modified. This can easily be changed to only alter items some percentage of the time instead of always.

socketSystem.lua needs to be a script entity in your dungeon.
socketItems.lua needs to be imported into your dungeons via init.lua.

Current gems available:

A base set of gems that increase stats/provide resistances. Elemental-themed, with qualities of gems that (Weapon , Armor , Shield ) Ruby: Fire damage/burning, fire resistance, health/vitality Sapphire: Cold damge/freezing, cold resistance, energy/willpower Topaz: Shock damage, shock resistance, critical/strength Emerald: Poison damage, poison resistance, accuracy/dexterity Diamond: AttackPower, resistAll, protection Amethyst: accuracy, evasion, evasion

Light Skull: Changes weapon requirement to light_weapons or switches heavy_armor to light_armor Heavy Skull: Changes weapon requirement to heavy_weapons or switches light_armor to heavy_armor Magic Skull: Changes weapon requirement to concentration

This will be expanded to include secondary actions, such as spells and special weapon attacks, only available after socketing a gem into a weapon.

To manually create an item with the ability to accept gems, the weapon/armor requires two components:

A Counter component named "sockets", set to the max amount of gems the item can accept.
A Counter component named "gemcount", initially set to the same value as "sockets". This is decreased when enchanting an item and prevents gems from being used when at 0.
Currently shields, chest pieces, and non-RunePanel weapons can be enchanted. Shields are given 1 slot, chest pieces are given two, and weapons are given 1 slot each (Except weapons with the "two_handed" trait are given two slots).

To modify an item, place one of the gems into a champion's hand along with the item to enchant in the other hand. Right-click the gem to enchant the other item being held. The gem will vanish and print out the effect of the gem.

If the other item being held does not have the correct components to be enchanted then it will print out that fact and the gem will remain in the champion's hand. Similarly, if the item has no more free sockets then the gem will have no effect and remain in hand.

To-do:

Find a better way to display the amount of free sockets in items. Currently, an item with a gameEffect will have it erased and replaced with the free socket count.
Increase the 3d models. Currently, some gems look a different color than they should due to the limited standard asset models available. I just need to sit down and learn how to modify them.
Included in the root of the textures folder is some item Atlases made available on the Grimrock forums, to differentiate the 2d gems a little bit. Akroma's icons: http://www.grimrock.net/forum/viewtopic.php?f=22&t=8058
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github

User avatar
Slade
Posts: 36
Joined: Tue Oct 21, 2014 6:31 pm

Re: CameronC's items/scripts (NEW: the socketSystem)

Post by Slade » Fri Dec 26, 2014 7:07 pm

Nice work! Hey,i did get the sockets working but now its says this in console when i start game : Warning! invalind component property item.gemcount
Warning! invalind component property item.sockets
Warning! invalind component property model.gemcount
Warning! invalind component property model.sockets
(edit)When i add ascended items too, now i cant even get the sockets working thought i did the same thing.
What i am doing wrong? I think its just little thing but i dont know what.. please help if you know(im just learning these things)
Thanks -Slade :)

cameronC
Posts: 80
Joined: Wed Apr 11, 2012 10:54 pm

Re: CameronC's items/scripts (NEW: the socketSystem)

Post by cameronC » Fri Dec 26, 2014 7:34 pm

Slade wrote:Nice work! Hey,i did get the sockets working but now its says this in console when i start game : Warning! invalind component property item.gemcount
Warning! invalind component property item.sockets
Warning! invalind component property model.gemcount
Warning! invalind component property model.sockets
(edit)When i add ascended items too, now i cant even get the sockets working thought i did the same thing.
What i am doing wrong? I think its just little thing but i dont know what.. please help if you know(im just learning these things)
Thanks -Slade :)
I just made a new dungeon and added the sockets only and it worked fine without anything being written to the console. I then added the unique items and still, no console output, and all the items that can have sockets function fine and can be modified. Are you adding the components manually? You just add these two new Components, without altering any pre-existing components of the items...

Code: Select all

{
		class = "Counter",
		name = "sockets",
		value = 2
		},
{
		class = "Counter",
		name = "gemcount",
		value = 2
		},
Writer and sometimes artist of the very slightly acclaimed comic series Scrambled Circuits. A comic series about a robot written by a human.

Grimrock 2 socketSystem: viewtopic.php?f=22&t=8546 / Github

User avatar
Slade
Posts: 36
Joined: Tue Oct 21, 2014 6:31 pm

Re: CameronC's items/scripts (NEW: the socketSystem)

Post by Slade » Fri Dec 26, 2014 8:18 pm

cameronC wrote:
Slade wrote:Nice work! Hey,i did get the sockets working but now its says this in console when i start game : Warning! invalind component property item.gemcount
Warning! invalind component property item.sockets
Warning! invalind component property model.gemcount
Warning! invalind component property model.sockets
(edit)When i add ascended items too, now i cant even get the sockets working thought i did the same thing.
What i am doing wrong? I think its just little thing but i dont know what.. please help if you know(im just learning these things)
Thanks -Slade :)
I just made a new dungeon and added the sockets only and it worked fine without anything being written to the console. I then added the unique items and still, no console output, and all the items that can have sockets function fine and can be modified. Are you adding the components manually? You just add these two new Components, without altering any pre-existing components of the items...

Code: Select all

{
		class = "Counter",
		name = "sockets",
		value = 2
		},
{
		class = "Counter",
		name = "gemcount",
		value = 2
		},


Thanks man! yes..i did add them manually and wrong way, now it works, wohoo! Lots of love for you <3 :) This is an awesome feature!
(edit) now i see that there is socket on every item even i put that your line only to "dagger" so where i need to write that,or how you choose which item has sockets? sorry for dump questions.

Post Reply