New Spells >> show them off here

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Merethif
Posts: 274
Joined: Tue Apr 24, 2012 1:58 pm
Location: Poland

Re: New Spells >> show them off here

Post by Merethif »

Grimwold wrote:
crisman wrote: Ah, good advice! Still I don't understand why it works fine for me thought...
Did not notice killing a creature with a mine you don't get exp. That's a real problem, and I don't think I could solve it so easily... oh well, unless considering it the price for being a coward by using such sneaky tricks :mrgreen: :mrgreen:
Never tried with a charging ogre?? That was the original purpose I had in mind! :D
Yeah, not sure why it works for you and not others.

Even without XP, it's useful for reducing the monsters health. As long as the killing blow comes from a weapon or direct damage spell, the party will get XP.
I've done what Grimwold suggested and it works now. To avoid XP lost I've tried to make freezing mine that would deal 0 damage and serve only as utility spell.
I've added:
attackPower = 0,
damageType = "cold",
freezeChance = 90,
freezeDuration = 5,
But sadly it didn't work. Anyway if someone would be able to add freezing effect to mine spell it would solve EX problem. Unless it is solvable by other means without taking away damage - which would be of course much better.


EDIT:
For just a brief moment I though I come up with something clever about spell mines, but no, not really :oops: Actually not at all.
All this hammer thinking made me think about Spirit Hammer (and I'm not the only one: viewtopic.php?f=14&t=3683&start=10#p38341). That's why I was experimenting with JKos's Magic Missile spell and replacing arrow with translucent bluish ogre hammer. Then testing some things like speed and rotation by trying different numbers in different places I came up with below spell:
SpoilerShow

Code: Select all

    defineSpell{
          name = "skull_sentry",
          uiName = "Skull Sentry",
          skill = "fire_magic",
          level = 2,
          runes = "AH",
          manaCost = 15,
          onCast = function(champ, x, y, direction, skill)
            local dx,dy = getForward(party.facing)
            playSoundAt("skeleton_die",party.level,party.x,party.y)
            shootProjectile('magic_missile', party.level, party.x+dx, party.y+dy, direction, 0, 0, 0, 0, 0, 0, skill*9, nil, true)
         end
    }

    defineObject{
          name = "skull_sentry",
          class = "Item",
          uiName = "Skull Sentry",
          model = "assets/models/items/skull.fbx",
          gfxIndex = 31,
	  attackPower = 1,
	  damageType = "fire",
          particleEffect = "fireball",
          stackable = false,
          sharpProjectile = false,
	  projectileRotationSpeed = -3,
          weight = 0.1,
    }
Generally it is a mine, but sadly not only it doesn't gives XP but also damages a party if party walk into it :o Anyway it looks sort of funny so I'm posting it here just for laughs.
User avatar
Currann
Posts: 7
Joined: Mon Oct 15, 2012 3:38 am

Re: New Spells >> show them off here

Post by Currann »

Grimwold wrote:
Currann wrote: That is probably it, but wouldnt calling the spell to cast "fireball" instead of "unstoppable_fireball" not do anything different? Either way, i tried the code, and my editor gives my a Warning saying "Warning! unkown buit-in-spell: unstoppable_fireball
I had a bit of a look at this last night but didn't get chance to post anything. Most things I tried either didn't work or crashed the game... So it looks like you can't do things quite how you want.

Using

Code: Select all

onCast = "fireball"
specifically calls a built-in spell called fireball (this uses but does not refer specifically to the object definition for fireball.

so putting

Code: Select all

onCast = "unstoppable_fireball"

will never work because unstoppable_fireball is not a built-in spell.

Also, while you can re-define the fireball object and perhaps tweak a few parameters, it's clear that the built-in portion of fireball is looking for some specific settings that it doesn't find if you try to replace it with, say, ice_shards.

So it looks to me like there isn't a shortcut to what you want to do and I'm convinced that your best bet is to define a new spell called unstoppable_fireball and actually script the spell within the onCast hook.

e.g.

Code: Select all

onCast = function(caster,x,y,facing,skill)
 -- script your spell here
 -- e.g. spawn("unstoppable_fireball",x,y,facing)
end
unfortunately this may mean re-inventing the wheel.
That does make sense. Now to create an object to do that, i'll most likely try this spell again when i have more experience.

Another question, where would i place the onProjectileHit hook for a monster? Because i have the idea to recreate the fireball projectile after it hits the monster
Szragodesca
Posts: 59
Joined: Sun Oct 14, 2012 7:13 am

Re: New Spells >> show them off here

Post by Szragodesca »

Ok, I played around with it for a bit and I got the custom fireball to spawn, modifying the attack power showed that it was truly the custom object being used.

in the spells.lua, I have:
SpoilerShow

Code: Select all

    defineSpell{
      name = "unstoppable_fireball",
      uiName = "Unstoppable Fireball",
      skill = "fire_magic",
      level = 1,
      runes = "E",
      manaCost = 30,
      onCast = function(caster, x, y, direction, skill)
        local dx,dy = getForward(party.facing)
        local x,y = party.x + dx, party.y + dy
        if party.facing == 0 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        elseif party.facing == 1 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        elseif party.facing == 2 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        else
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        end
    end
   }
and in objects.lua:
SpoilerShow

Code: Select all

    cloneObject{
      name = "unstoppable_fireball",
      baseObject = "fireball",
      particleEffect = "fireball_greater",
      sound = "fireball",
      uiName = "Unstoppable Fireball",
      attackPower = math.random(25,75),
      damageType = "fire",
   }
Now, the problem here is that it acts just like a normal fireball. Fire once and it's done. I did change the "baseObject" to "ice_shards" but it didn't overwrite the particle effect or sound, and it applied full damage to the first tile but not the ones after (testing on a line of crates). I had nested the directional spawn code of the spells.lua in a while loop, but it didn't work as I'd intended (spawn fireball, decrement variable, spawn again, decrement again, until variable = 0 at which point the loop ends). Then again, I'm still a scripting newb and probably wrote something wonky. My next idea uses a table, but I don't have time to try it tonight since I have to get ready for work soon. I also wanted to override the object's power with "math.random(5,10)*caster.getSkillLevel("fire_magic")", but it crashed my editor no matter how I tried to add that in. I couldn't put it in the Object's code, because that doesn't understand "caster" or "getSkillLevel". This way, if you learned the spell at (for example) fire_magic 15, you would do 75-150 damage per tile (probably more, as my default amount hits up to 96). At skill of 50, that would be 250-500 per tile, which is painful. :?

What I'll try is to generate a table where each variable in the list adds to the "local x,y", and nest it in a for loop. Have it go one at a time through the variables of the list, and each time it spawns a fireball one square farther away from the last for 5 squares (to avoid launching multiple fireballs from empty tiles, I'm thinking of changing this to a fireburst object). Then, in effect, it should make a path of fire which I think is the original intent of the spell. . . no? (perhaps the last square will launch a fireball version, so it can then travel) The reason for this is so you don't have to throw in script elements and counters to the map, just cast the spell and it does the work internally. I know Grimwold could use counters and script elements to cause the recurring effect, he's done such similar things with other spells already, and I'd be fine with that if it were set up and working. The benefit of keeping it all in the spell's code, though, is each map maker doesn't have to add in the map contents to make the spell work. ;)

Tying it to counters (or a counting-down internal code) and spawning a gfx of the fireball flying through the detonating tiles would, of course, be the final "ooh, ahh" ideal, but for now i'll just be happy to see it hit multiple tiles. :lol:
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: New Spells >> show them off here

Post by akroma222 »

Hey Bilchew!
sure, this is what I found:
SpoilerShow
mod_assets/scripts/objects.lua:844: bad argument #1 to 'getChampion' (number expected, got table)
stack traceback:
[C]: in function 'error'
[string "ScriptInterface.lua"]: in function 'getChampion'
mod_assets/scripts/objects.lua:844: in function 'onCast'
[string "Spells.lua"]: in function 'castSpell'
[string "Champion.lua"]: in function 'castSpell'
[string "AttackPanel.lua"]: in function 'update'
[string "AttackPanel.lua"]: in function 'update'
[string "Gui.lua"]: in function 'draw'
[string "GameMode.lua"]: in function 'update'
[string "DungeonEditor.lua"]: in main chunk
line 844 does correspond to the getChampion command for Enchant Arrow in objects.lua
I did not have any time to play today so no further progress on my end for now...
much appreciated man!
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: New Spells >> show them off here

Post by Grimwold »

@Szragodesca
looks like you have redundant spawn lines nested in if statements.. with the use of getForward() there should be no need to test party.facing.

also, the spell passes the variable "skill" anyway, so you don't need caster:getSkillLevel
so this should work

Code: Select all

math.random(5,10)*skill

I also had a play with this last night, but I don't have the code to hand that I wrote. Basically when the spell was cast it:
1) spawned a timer with short duration & activated it
2) spawned a counter set to 1

Each time the timer activated it called a function that spawned a fireburst in the space (x + counter:getValue()*dx, y + counter:getValue()*dy) and incremented the counter. It did this until counter:getValue() > 4 and then it destroyed the timer and the counter...
This had the illusion of creating firebursts in the 4 spaces in a line in front of the player.

This looked quite effective, but the main problems I had were
a) no experience for the party if the monsters died from this spell (an issue for all custom damage spells)
b) I was using party.x and party.y so if the party moved while the spell was going off it changed the target spaces!! e.g. sidestepping!

One solution to b) is to store x and y as variables in the script entity, but it was 2am and I didn't have time to finish it!!
Szragodesca
Posts: 59
Joined: Sun Oct 14, 2012 7:13 am

Re: New Spells >> show them off here

Post by Szragodesca »

Yeah, I was kinda rushed since I posted that like, 3 minutes before I had to get ready for work. :lol: Normally I would have caught the "skill" check (because I had earlier with a failed attempt, but after later trying to tie it to the object I pulled that back into the script and forgot).

As for the if statements, I know there has to be a cleaner way to do it, but I don't know that way. I'm an idea guy, not the one who provides the finished product. (Even back when I did NWScripting I could release a fully functional thing, and someone would come along and clip it down to half my size, lol) I chop-shop coded that due to my time limitations, so most of the code is pulled from other spells in this thread. I knew it worked in them, so I took it and checked if it would work in this. My goal was more to get it working and let someone clean it up than perfect it on my own. ;) Glad to hear you got the firing mostly working, and along similar lines to what I'd thought might work.

As for XP, can you read the XP value of the target and, if the spell kills it, award that to each active champ appropriately? I don't know if LoG applies the full value to all champs (provided they hit the mob, I know that part), or if it takes full XP and divides it by champs. . . I know the mobs have an XP value as I saw it written in the monster levels discussion in another thread, just don't know how one would access it yet. I'll have to get the asset pack home and start poking around. You'd probably have to get the ID and XP value of each affected monster, then run a check to see if the ID still existed after the damage was applied and monster destroyed. If the monster is still up, no XP. If it's gone, award XP. Would that work as a roundabout?
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: New Spells >> show them off here

Post by Grimwold »

Full EXP to all champs that hit. 50% EXP to any champs that didn't.
I think it might be quite tricky to figure out if any monsters died during the spell and award EXP appropriately.

regarding the spawn code, you've already done all the work and your spawn lines are identical so just replace all with a single spawn:

Code: Select all

    defineSpell{
          name = "unstoppable_fireball",
          uiName = "Unstoppable Fireball",
          skill = "fire_magic",
          level = 1,
          runes = "E",
          manaCost = 30,
          onCast = function(caster, x, y, direction, skill)
            local dx,dy = getForward(party.facing)
            local x,y = party.x + dx, party.y + dy
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        end
       }
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: New Spells >> show them off here

Post by Grimwold »

@akroma222
akroma222 wrote: line 844 does correspond to the getChampion command for Enchant Arrow in objects.lua
I did not have any time to play today so no further progress on my end for now...
much appreciated man!
The problem with this line
party:getChampion(caster):getItem(7)
is because getChampion() expects a number from 1 to 4 and caster is an instance of the Champion Class.

What you can do instead is something like

Code: Select all

caster:getItem(7)
Which returns an entity for the item in the caster's left hand. Since this is an entity you will need to call a function to get it's name if you want to compare it...

e.g. This will print to the HUD the name of the item in the caster's left and right hands.

Code: Select all

hudPrint(caster:getItem(7):getUIName())
hudPrint(caster:getItem(8):getUIName())
User avatar
Currann
Posts: 7
Joined: Mon Oct 15, 2012 3:38 am

Re: New Spells >> show them off here

Post by Currann »

Grimwold wrote:@Szragodesca
looks like you have redundant spawn lines nested in if statements.. with the use of getForward() there should be no need to test party.facing.

also, the spell passes the variable "skill" anyway, so you don't need caster:getSkillLevel
so this should work

Code: Select all

math.random(5,10)*skill

I also had a play with this last night, but I don't have the code to hand that I wrote. Basically when the spell was cast it:
1) spawned a timer with short duration & activated it
2) spawned a counter set to 1

Each time the timer activated it called a function that spawned a fireburst in the space (x + counter:getValue()*dx, y + counter:getValue()*dy) and incremented the counter. It did this until counter:getValue() > 4 and then it destroyed the timer and the counter...
This had the illusion of creating firebursts in the 4 spaces in a line in front of the player.

This looked quite effective, but the main problems I had were
a) no experience for the party if the monsters died from this spell (an issue for all custom damage spells)
b) I was using party.x and party.y so if the party moved while the spell was going off it changed the target spaces!! e.g. sidestepping!

One solution to b) is to store x and y as variables in the script entity, but it was 2am and I didn't have time to finish it!!
Szragodesca wrote:Ok, I played around with it for a bit and I got the custom fireball to spawn, modifying the attack power showed that it was truly the custom object being used.

in the spells.lua, I have:
SpoilerShow

Code: Select all

    defineSpell{
      name = "unstoppable_fireball",
      uiName = "Unstoppable Fireball",
      skill = "fire_magic",
      level = 1,
      runes = "E",
      manaCost = 30,
      onCast = function(caster, x, y, direction, skill)
        local dx,dy = getForward(party.facing)
        local x,y = party.x + dx, party.y + dy
        if party.facing == 0 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        elseif party.facing == 1 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        elseif party.facing == 2 then
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        else
            spawn("unstoppable_fireball", party.level, x, y, party.facing)
        end
    end
   }
and in objects.lua:
SpoilerShow

Code: Select all

    cloneObject{
      name = "unstoppable_fireball",
      baseObject = "fireball",
      particleEffect = "fireball_greater",
      sound = "fireball",
      uiName = "Unstoppable Fireball",
      attackPower = math.random(25,75),
      damageType = "fire",
   }
Now, the problem here is that it acts just like a normal fireball. Fire once and it's done. I did change the "baseObject" to "ice_shards" but it didn't overwrite the particle effect or sound, and it applied full damage to the first tile but not the ones after (testing on a line of crates). I had nested the directional spawn code of the spells.lua in a while loop, but it didn't work as I'd intended (spawn fireball, decrement variable, spawn again, decrement again, until variable = 0 at which point the loop ends). Then again, I'm still a scripting newb and probably wrote something wonky. My next idea uses a table, but I don't have time to try it tonight since I have to get ready for work soon. I also wanted to override the object's power with "math.random(5,10)*caster.getSkillLevel("fire_magic")", but it crashed my editor no matter how I tried to add that in. I couldn't put it in the Object's code, because that doesn't understand "caster" or "getSkillLevel". This way, if you learned the spell at (for example) fire_magic 15, you would do 75-150 damage per tile (probably more, as my default amount hits up to 96). At skill of 50, that would be 250-500 per tile, which is painful. :?

What I'll try is to generate a table where each variable in the list adds to the "local x,y", and nest it in a for loop. Have it go one at a time through the variables of the list, and each time it spawns a fireball one square farther away from the last for 5 squares (to avoid launching multiple fireballs from empty tiles, I'm thinking of changing this to a fireburst object). Then, in effect, it should make a path of fire which I think is the original intent of the spell. . . no? (perhaps the last square will launch a fireball version, so it can then travel) The reason for this is so you don't have to throw in script elements and counters to the map, just cast the spell and it does the work internally. I know Grimwold could use counters and script elements to cause the recurring effect, he's done such similar things with other spells already, and I'd be fine with that if it were set up and working. The benefit of keeping it all in the spell's code, though, is each map maker doesn't have to add in the map contents to make the spell work. ;)

Tying it to counters (or a counting-down internal code) and spawning a gfx of the fireball flying through the detonating tiles would, of course, be the final "ooh, ahh" ideal, but for now i'll just be happy to see it hit multiple tiles. :lol:
Thank you, you two. These posts were able to give me an almost succesful code!
I have:

Code: Select all

defineSpell{
      name = "unstoppable_fireball",
      uiName = "Unstoppable Fireball",
      skill = "fire_magic",
      level = 1,
      runes = "E",
      manaCost = 30,
      onCast = function(caster,x,y,facing,skill)
		local dx,dy = getForward(party.facing)
        local x,y = party.x + dx, party.y + dy
		local xIncrease = 0
		local yIncrease
        if party.facing == 0 then
			while yIncrease > -20 do
				if y-yIncrease <= 0 then
					yIncrease = yIncrease - 1
				else
					spawn("fireburst", party.level, x, y-yIncrease, party.facing)
					yIncrease = yIncrease - 1
				end
			end
        else if party.facing == 1 then
            while xIncrease < 20 do
				if x+xIncrease >= 31 then
					xIncrease = xIncrease + 1
				else
					spawn("fireburst", party.level, x+xIncrease, y, party.facing)
					xIncrease = xIncrease + 1
				end
			end
        else if party.facing == 2 then
            while yIncrease < 20 do
				if y+yIncrease >= 31 then
					yIncrease = yIncrease + 1
				else
					spawn("fireburst", party.level, x, y+yIncrease, party.facing)
					yIncrease = yIncrease + 1
				end
			end
        else
            while xIncrease > -20 do
				if x-xIncrease <= 0 then
					xIncrease = xIncrease - 1
				else
					spawn("fireburst", party.level, x-xIncrease, y, party.facing)
					xIncrease = xIncrease - 1
				end
			end
        end
	end

	}
But whenever i try to load it into the editor, it gives me a warning, saying: unexpected symbol near '}'
Probably just an extra 'end', but i couldnt find it.
User avatar
Filipsan
Posts: 84
Joined: Fri Mar 16, 2012 10:18 am

Re: New Spells >> show them off here

Post by Filipsan »

Code: Select all


defineSpell{
   name = "unstoppable_fireball",
   uiName = "Unstoppable Fireball",
   skill = "fire_magic",
   level = 1,
   runes = "E",
   manaCost = 30,
   onCast = function(caster,x,y,facing,skill)
   local dx,dy = getForward(party.facing)
   local x,y = party.x + dx, party.y + dy
   local xIncrease = 0
   local yIncrease

   if party.facing == 0 then
      while yIncrease > -20 do
         if y-yIncrease <= 0 then
            yIncrease = yIncrease - 1
         else
            spawn("fireburst", party.level, x, y-yIncrease, party.facing)
            yIncrease = yIncrease - 1
         end
      end
   else if party.facing == 1 then
      while xIncrease < 20 do
         if x+xIncrease >= 31 then
            xIncrease = xIncrease + 1
         else
            spawn("fireburst", party.level, x+xIncrease, y, party.facing)
            xIncrease = xIncrease + 1
         end
      end
   else if party.facing == 2 then
      while yIncrease < 20 do
         if y+yIncrease >= 31 then
            yIncrease = yIncrease + 1
         else
            spawn("fireburst", party.level, x, y+yIncrease, party.facing)
            yIncrease = yIncrease + 1
         end
      end
   else
      while xIncrease > -20 do
         if x-xIncrease <= 0 then
            xIncrease = xIncrease - 1
         else
            spawn("fireburst", party.level, x-xIncrease, y, party.facing)
            xIncrease = xIncrease - 1
         end
      end
   end
   end
}
indeed, last end is extra IMO :)
Post Reply