Page 1 of 1

Running script with Champion.OnAttack?

Posted: Thu Jan 10, 2013 10:24 am
by Vaguereach
Hello there,

I'm writing a mod that implements a damage increase for missile weapons based on dexterity. I have a formula in mind and a plan of action but I have (potentially) two concerns...

Is there a way to execute a script when a monster is hit/takes damage or alternatively when a player attacks? I.e. something using the onAttack or onProjectileHit hooks? (which I don't yet know how to make trigger a script)

I know how to retrieve the champions dexterity and strength etc and how to use that value as a string or integer, but since I literally started learning Lua and using the dungeon editor about 3 hours ago, I'm hoping to avoid potential rookie pitfalls that could be solved by a community like you guys!

Cheers

Re: Running script with Champion.OnAttack?

Posted: Thu Jan 10, 2013 12:50 pm
by Komag
You'll want to refer to http://www.grimrock.net/modding/asset-d ... reference/
You might use monster onDamage or onProjectileHit, or party onAttack (not onProjectileHit because that is when the party is hit). Party onAttack sounds like the closest match to what you want.

To use the hook you need to clone the party object and define the hook into it. Make sure you have downloaded the asset pack and look at the objects script to see the full original party object. You will do a clone and add the hook and then link to a script name that you put in your dungeon. This keeps the hook simple. Then in your dungeon, put all your code in the script item.

In your objects.lua file (in your dungeon scripts folder deep in your documents folder):

Code: Select all

cloneObject{
  name = "party",
  baseObject = "party",
  onAttack = function(champ,weapon)
    dexAttackScript.dexAttack(champ,weapon)
  end,
}
in the dexAttackScript script entity (the little "lua" item you put in the dungeon via the editor):

Code: Select all

str = 0
ch = 0

dexAttack(champ,weapon)
  ch = champ:getOrdinal()
  str = champ:getStatMax("strength")
  local dex = champ:getStatMax("dexterity")
  if weapon == "sling" or weapon == "short_bow" or weapon "crossbow" or weapon == "longbow" then
     champ:setStatMax("strength", str+(dex*0.5)) -- change 0.5 to whatever you want
     champ:setStat("strength", str+(dex*0.5))
  end
  spawn("timer",party.level,party.x,party.y,0,"dexAttackTimer")
   :setTimerInterval(0.03)
   :addConnector("activate", "dexAttackScript", "strReset")
   :activate()
end

strReset()
  party:getChampion(ch):setStatMax("strength", str)
  dexAttackTimer:destroy()
end
I wrote this off the cuff so I may have made some mistakes or completely forgot about some aspect, but I hope it helps :)

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 8:35 am
by Vaguereach
I've made a working script using the onDamage hook but I think you were right when you suggested basing it off the onAttack of the party. Not only does that save me cloning every single monster in the game, it also passes the right information (I didn't realize that the missle damage type was physical... I thought it was ranged, or missle, etc) which onDamage doesn't do.

Looking over your script again, even though you did it off the cuff I'll credit you if I use any part of it :)

Thanks man!

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 10:12 am
by Vaguereach
Hmmm...

If I use

Code: Select all

weap = tostring(party:getChampion(x):getItem(7))
where x is equal to the ordinal number of the champion, I'm passed information from a table which seems to the weapon ID and not the weapon name.

I.e. by printing weap with print(weap) I receive "table: 0x0f46ad60".

Note that this number changes on each play, so it's based off the 'spawned' weapon.

How do I convert that number to a weapon name or, alternatively, how do I just retrieve the weapon name?

Thanks

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 10:45 am
by Vaguereach
P.S. -

I'm thinking I might need to change something in the objects.lua?

I.e. when the onAttack hook triggers, should I be passing the weapon.uiName or something as opposed to just the weapon?

the onAttack hook for the party apparently "gets the attacking champion and the weapon used to attack" but I have no idea what 'weapon used' translates too... the name, the object ID (apparently)... argh.

Super annoying problem.

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 11:10 am
by Vaguereach
Fixed it by using weap.name (instead of just weap).

So simple.

Will update when I have finished working script.

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 1:17 pm
by Komag
Oops, that was my bad, forgot to add the .name there! Glad you figured it out :)

BTW, I think this concept would probably work better use onEquipItem or onUnequipItem hooks, so that the bonus effect could be seen immediately right on your inventory screen. There might be other considerations too, such as whether they are holding skulls (if minotaur) and how that might affect current strength, whether they have any other dex enhancing hear equipped, etc

Re: Running script with Champion.OnAttack?

Posted: Sat Jan 12, 2013 2:10 pm
by Vaguereach
That's a good thought too - having it apply on equip item might involve considerably more code (or not ... hmmm) but it would allow the dexterity bonus applied to bow damage feel more intuitive and natural. My only concern is having to check all item equip slots (including backpack for head hunting Minotaurs) every time an item is equipped or placed into a backpack, and then after stat points are applied after a level up.

I think your first instinct to go with the onAttack seems, for now, to be the way to go. But we will see! I had the onProjectileHit working on my cloned snails but realized it would be too difficult if not impossible to implement what I want ha ha

Re: Running script with Champion.OnAttack?

Posted: Sun Jan 13, 2013 4:30 am
by Vaguereach
Soo... now I'm stuck trying to use a numeric for loop.

I don't know if it's because I'm referencing the spawner in my level incorrectly or because I need to use a generic for loop...

This is an aside, I'm just familiarising myself with the language.

Cheers!

Code: Select all

function skeleSpawn()
		for i=1,3 do
		skelespawn(i):activate()
		skelespawn(i):destroy()
		end
end

Re: Running script with Champion.OnAttack?

Posted: Sun Jan 13, 2013 7:24 pm
by Komag
it looks okay codewise, but The problem is most likely that you're trying to destroy them at what effectively is the same time as activating them. Try just activating for the test. If you want to delete, do it after a short timer. Better yet, just use spawn code instead of spawner objects for one-off spawns