Putting the 'role' back in role-playing games since 2002.
Donate to Codex
Good Old Games
  • Welcome to rpgcodex.net, a site dedicated to discussing computer based role-playing games in a free and open fashion. We're less strict than other forums, but please refer to the rules.

    "This message is awaiting moderator approval": All new users must pass through our moderation queue before they will be able to post normally. Until your account has "passed" your posts will only be visible to yourself (and moderators) until they are approved. Give us a week to get around to approving / deleting / ignoring your mundane opinion on crap before hassling us about it. Once you have passed the moderation period (think of it as a test), you will be able to post normally, just like all the other retards.

Making new spells for ToEE - Discussion

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
@Sitra: Time has been an obstacle as of late. If y'all had TemplePlus or similar, easy modding capabilities in 2006 or so, I may have been very into that instead of WoW. I did make Ronald Rinnwrathi, the companion NPC Cleric, but ShiningTed did the coding to make him work.

As of late, I've been working on my teaching credential and master's degree in education for California. Much of my playtime has become worktime and I've generally been OK with that because work done well means real life progress!

Speaking of which, Sitra, how do you have so much time as of late to work on T+? (I'm quite grateful for it. Alleluia!)
 
Last edited:

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
I tried the making a new spell, greater mage armor from Spell Compendium. I used Notepad++ to edit the Mage Armor python file and made Spell3001 - Greater Mage Armor.py. It functions as Mage Armor, but is Sor/Wiz3 and provides a +6 armor AC bonus instead of +4. I also changed all references in this file of 'Mage Armor' to 'Greater Mage Armor,' except sounds and graphics (SFX and GFX respectively).

In data\rules\spells, I made a rules file for GMA called 3001 - Greater Mage Armor.txt. I took inspiration from Neutralize Poison, Power Word Blind, and Haste to make the rules file.

How to get this working in-game with a scribable scroll? Presently, the game crashes on loading when I have these files in the proper directories.

I also modified Acid Fog to be Endarire's Acid Fog at spell ID 3000 since Acid Fog wasn't showing up/working properly before due to being at ID 0. How to get that working too with a scribable scroll?

Finally, I'm on a Windows 7 Ultimate Edition machine.
 
Last edited:

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
Regarding fixing the crashing: I may need something in protos.tab, but I'm currently unsure what, where, and how.
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
I tried the making a new spell, greater mage armor from Spell Compendium. I used Notepad++ to edit the Mage Armor python file and made Spell3001 - Greater Mage Armor.py. It functions as Mage Armor, but is Sor/Wiz3 and provides a +6 armor AC bonus instead of +4. I also changed all references in this file of 'Mage Armor' to 'Greater Mage Armor,' except sounds and graphics (SFX and GFX respectively).

In data\rules\spells, I made a rules file for GMA called 3001 - Greater Mage Armor.txt. I took inspiration from Neutralize Poison, Power Word Blind, and Haste to make the rules file.

How to get this working in-game with a scribable scroll? Presently, the game crashes on loading when I have these files in the proper directories.

I also modified Acid Fog to be Endarire's Acid Fog at spell ID 3000 since Acid Fog wasn't showing up/working properly before due to being at ID 0. How to get that working too with a scribable scroll?

Finally, I'm on a Windows 7 Ultimate Edition machine.

Spell enums 3000 are reserved for class abilities. In particular, 3000-3007 are already taken for the Bard's spells. Making duplicates will crash the game.
I've reserved the range of spell enums 951-999 for you.

You should also read the log file if it crashes when modding, it will often tell you what went wrong.
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
I changed spell IDs to the reserved range, and...

Greater mage armor worked as intended! Alleluia!

Endarire's acid fog just made solid fog from a level 6 spell slot. Needs more work.

How to make scrolls of these spells that Wizards can learn? How to make these scrolls craftable?
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
It isn't a new spell, but I fixed Melf's acid arrow to allow for higher caster levels. This file accounts for CL57+.

LINK
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
I changed spell IDs to the reserved range, and...

Greater mage armor worked as intended! Alleluia!

Endarire's acid fog just made solid fog from a level 6 spell slot. Needs more work.

How to make scrolls of these spells that Wizards can learn? How to make these scrolls craftable?

I've updated the Making Spells For ToEE post with relevant info.
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
It isn't a new spell, but I fixed Melf's acid arrow to allow for higher caster levels. This file accounts for CL57+.

LINK

You just triggered me :P

Instead of typing a long ass list of ranges, why not do:
Code:
dur = spell.caster_level / 3
if dur < 0:
   dur = 0
elif dur > 20:
   dur = 20
spell.duration = dur

Also, you need to use the updated spell script from tpgamefiles.dat - the perform_touch_attack method has been altered to accomodate spell sneak attacks.

Lastly, this is homebrew I take it? The SRD says it goes up to caster level 18th.
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
Melf's: Oops! I didn't realize there was a CL cap of 18.

I would have used a caster level/3 thingy had I known I were working with ints (INTs?). I didn't want to cause further errors.

I modified the script because for caster levels above 20, the script was wrong.

So, what's the full process now for editing spells and submitting them to you? I got confused. I thought it was a simple matter of editing the .PY and .TXT files.
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
Oh, if you have a final and tested version by all means submit it for inclusion. I'll open a new thread titled 'Mod Submissions for Temple+' so it's easier to keep track.
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
The Co8 version of Melf's acid arrow is only correct for caster levels 20 and below. Above CL20, the duration was listed as 1-1. It seems like a simple fix to change the condition so it's the same duration for CL 18+.
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
Any plans to include ShiningTed's domain spell mod for T+? What about your own vigor series of spells? Just curious.
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
Any plans to include ShiningTed's domain spell mod for T+? What about your own vigor series of spells? Just curious.
I wasn't planning on distributing other peoples mods unless they expressly ask for it. It's a bit sad how they buried it in that thread though. I've nudged them a couple of times to make it better known and got no reaction, if you care then perhaps you should too.
 

Etharil

Novice
Joined
Oct 16, 2016
Messages
63
Location
Ulcaster Ruins
Sorry for disappearing - my monitor is currently broken (capacitors died, so not enough power to launch, basically) and I'm waiting for a replacement one.
 

Endarire

Scholar
Joined
Feb 28, 2016
Messages
395
Welcome Back, Etharil! We (and, apparently, especially I) have work to do for T+!
 

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
I'm trying to understand custom conditions and event objects, can I get an explanation why this doesn't work?

I'm modifying Spell439 - Sleet Storm.py that's in my overrides/scr folder. I've renamed the 'sp-Sleet Storm' condition to 'sleetStorm' and removed excess baggage.

The custom python modifier is in sleet.py in my overrides/scr/tpModifiers folder. All I'm trying to do is to get a text float to appear when you enter the AoE.

Code:
from toee import *

def OnBeginSpellCast( spell ):
    game.particles( "sp-conjuration-conjure", spell.caster )

def OnSpellEffect( spell ):
    spell.duration = 1 * spell.caster_level

    # spawn one spell_object object
    spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc )

    # add to d20initiative
    caster_init_value = spell.caster.get_initiative()
    spell_obj.d20_status_init()
    spell_obj.set_initiative( caster_init_value )

    # put sp-Sleet Storm condition on obj
    spell_obj_partsys_id = game.particles( 'sp-Sleet Storm', spell_obj )
    spell_obj.condition_add_with_args( 'sleetStorm', spell.id, spell.duration, 0, spell_obj_partsys_id )

def OnBeginRound( spell ):

def OnEndSpellCast( spell ):

def OnAreaOfEffectHit( spell ):

def OnSpellStruck( spell ):

Code:
from templeplus.pymod import PythonModifier
from toee import *
import tpdp

def OnObjectEvent(attachee, args, evt_obj):
    tgt = evt_obj.target
    tgt.obj.float_mesfile_line( 'mes\\spell.mes', 30001 )

    return 0

sleetStorm = PythonModifier("sleetStorm", 4)
sleetStorm.AddHook(ET_OnObjectEvent, EK_NONE, OnObjectEvent, ())

In game the floating text never appears and the AoE never dissipates.

Also which event does evt_id refer to in EventObjObjectEvent?
 

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
I'm trying to understand custom conditions and event objects, can I get an explanation why this doesn't work?

I'm modifying Spell439 - Sleet Storm.py that's in my overrides/scr folder. I've renamed the 'sp-Sleet Storm' condition to 'sleetStorm' and removed excess baggage.

The custom python modifier is in sleet.py in my overrides/scr/tpModifiers folder. All I'm trying to do is to get a text float to appear when you enter the AoE.

Code:
from toee import *

def OnBeginSpellCast( spell ):
    game.particles( "sp-conjuration-conjure", spell.caster )

def OnSpellEffect( spell ):
    spell.duration = 1 * spell.caster_level

    # spawn one spell_object object
    spell_obj = game.obj_create( OBJECT_SPELL_GENERIC, spell.target_loc )

    # add to d20initiative
    caster_init_value = spell.caster.get_initiative()
    spell_obj.d20_status_init()
    spell_obj.set_initiative( caster_init_value )

    # put sp-Sleet Storm condition on obj
    spell_obj_partsys_id = game.particles( 'sp-Sleet Storm', spell_obj )
    spell_obj.condition_add_with_args( 'sleetStorm', spell.id, spell.duration, 0, spell_obj_partsys_id )

def OnBeginRound( spell ):

def OnEndSpellCast( spell ):

def OnAreaOfEffectHit( spell ):

def OnSpellStruck( spell ):

Code:
from templeplus.pymod import PythonModifier
from toee import *
import tpdp

def OnObjectEvent(attachee, args, evt_obj):
    tgt = evt_obj.target
    tgt.obj.float_mesfile_line( 'mes\\spell.mes', 30001 )

    return 0

sleetStorm = PythonModifier("sleetStorm", 4)
sleetStorm.AddHook(ET_OnObjectEvent, EK_NONE, OnObjectEvent, ())

In game the floating text never appears and the AoE never dissipates.

Also which event does evt_id refer to in EventObjObjectEvent?
Hey, I recommend checking out the blackguard.py Aura of Despair section for an example of how to do an AoE.
 

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
Hey, I recommend checking out the blackguard.py Aura of Despair section for an example of how to do an AoE.

Q1 - That was quite helpful, although I still don't understand evt_obj.evt_id. Is it the list of objects in the AoE?

Q2 - On another note, how does metamagic work when it comes to custom spells and conditions (which number/variable does maximize maximize, or widen widen)? If I have something like this hooked to ET_OnBeginRound, there's no way the engine is smart enough to increase the IF check number 20. How should metamagic be coded in?

Code:
tgts = game.obj_list_vicinity(attachee.location, OLC_CRITTERS)
for obj in tgts:
    if obj.distance_to(attachee) <= 20:
        print "target acquired"

Q3 - Is there some way to see the code for all the default functions/conditions? Like how do I know what the args are for vanilla conditions (or how could I possibly know the args for object_event_append() without seeing an example for it)? Or where do I see all the possible .commands like dice_new().bonus? Also how I do access the result for dice. For example...

Code:
number = dice_new('1d20')
print number

... returns "1d20", and not the actual result of the roll.

Q4 - What is the proper way to "end" a spell? What's the difference between spell.spell_end in the spell script and args.condition_remove() in the tpmodifier script? Which will destroy the spell object that's created in the spell script?

Q5 - Some explanations for the following event types would be helpful (ET_OnDispelCheck, ET_OnSpellImmunityCheck, ET_OnImmunityTrigger), what are they used for, and what do I need to code in these hooks manually? Is dispel magic smart enough to cancel a custom condition or do I need to code it in?

Q6 - is there a list of all possible variables and flags for the data/rules/spells file?

Q7 - is it possible to code a custom saving throw/opposing roll (without using a function like reflex_save_and_damage) where the result/breakdown of the roll appears in the roll information box as a hypertext link instead of directly writing it in with create_history_freeform.
 
Last edited:

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
Q8 - When making a new condition indicator (wiki link), how do you link the ID_string: to the custom condition? I tried just about everything I can think of, printing out the hash and using the numeric value as the first argument of the condition and passing it to evt_obj.append in ET_OnGetEffectTooltip function plus all kinds of desperate shit. The instruction on the wiki is woefully unclear on this matter. The only example that comes along with temple+ is inspire_heroics.txt, and it's ID_string: is nowhere to be found in the .py files.
 
Last edited:

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
Well I figured out evt_obj.evt_id is the spell.id, so that's Q1 off the list. Still need to know how to pass widen metamagic information to increase the radius for .object_event_append().

I checked python_dispatcher.cpp for metamagic and saw the heighten with // todo rest, so it might not even be possible atm? Unless you can pass the metamagic from the spell script.
 
Last edited:

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
Also figured out Q8 - but might as well post it here if anyone else if having trouble with it. It's actually in the wiki but kinda hard to find.

In the function you define for the ET_OnGetEffectTooltip hook, you must put evt_obj.append(effect_type_id, spell_enum, text_string)

effect_type_id is the tpdp.hash("ID_string") from the wiki, and text_string has to be defined (can't be left blank), you can use "" since tooltip_base_text: is in the custom indicator .txt file.

You can find all vanilla icons in ToEE1.dat, there's a nice .psd file with the background frame already done (along with all icons), but you have to create an alpha mask manually (black is transparent, white is opaque).
 
Last edited:

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
Q9 - I'm using the same kind of structure in my AoE as Aura of Despair, meaning...

Spell script creates spell object and adds condition #1 to it -> condition #1 adds condition #2 to those who enter the AoE

In condition #2 I'm using damage() function/method in a function hooked to ET_OnBeginRound, but the first arg of damage() is the damager, now how can I pass the spellcaster object to it when attachee refers to target and tpdp.SpellPacket doesn't have anything that returns the caster? I don't want to use OBJ_HANDLE_NULL because it's ugly in the roll information box.

Also what's the difference between damage() and spell_damage() functions?
 
Last edited:

Sitra Achara

Arcane
Joined
Sep 1, 2003
Messages
1,859
Codex 2012 Codex 2013 Codex 2014 PC RPG Website of the Year, 2015
Well I figured out evt_obj.evt_id is the spell.id, so that's Q1 off the list. Still need to know how to pass widen metamagic information to increase the radius for .object_event_append().

I checked python_dispatcher.cpp for metamagic and saw the heighten with // todo rest, so it might not even be possible atm? Unless you can pass the metamagic from the spell script.
The event ID is unrelated to spell ID. I surmise you tried this with a new game, which might have had the spell ID identical to event ID by coincidence (since both are serial numbers starting with 1).

I've added some doc on Object Events in the Wiki.

Re. Q2
For Metamagic Widen, as far as I can tell all non-transient AoEs in ToEE are static and do not regard Widen Spell... is that a bug?

Maximize/Empower are checked inside spell_damage() (and not on the ordinary damage() ).

Q3 - Is there some way to see the code for all the default functions/conditions? Like how do I know what the args are for vanilla conditions (or how could I possibly know the args for object_event_append() without seeing an example for it)? Or where do I see all the possible .commands like dice_new().bonus? Also how I do access the result for dice. For example...

In vanilla the args for object_event_append are always OLC_CRITTERS and the radius_target value from the spell entry.

There's some doc on the wiki on the python methods, but most of them are for PyObjHandle and PyGame.
dice_new() creates a PyDice object, whose methods and properties you can find in python_dice.cpp. Usually if you pass the dice itself as an argument you cannot see the result directly. You can use the .roll() method to get a result, but it won't be persistent or anything like that.

Q4 - What is the proper way to "end" a spell? What's the difference between spell.spell_end in the spell script and args.condition_remove() in the tpmodifier script? Which will destroy the spell object that's created in the spell script?
condition_remove() will remove a condition from the object. No more, no less.
spell_end() will remove a spell from the "currently active spell registry" (so it doesn't generate anymore events such as OnBeginRound etc.).
Usually you don't destroy the spell object itself, but rather end the AoE condition in a countdown callback. This can be tricky though (hence the many spell permanency issues ToEE has had).

I'll get to the rest and expand on ending spells using vanilla AoEs as examples when I have time. Gotta go to bed now ;)
 
Last edited:

cowking

Scholar
Joined
Oct 18, 2016
Messages
115
For Metamagic Widen, as far as I can tell all non-transient AoEs in ToEE are static and do not regard Widen Spell... is that a bug?

Maybe not in vanilla ToEE but definitely in pen and paper. Eg you should be able to widen web, which you can't currently. I guess the dev reason was the extra work to make gfx scale.

Q3 - Is there some way to see the code for all the default functions/conditions? Like how do I know what the args are for vanilla conditions (or how could I possibly know the args for object_event_append() without seeing an example for it)? Or where do I see all the possible .commands like dice_new().bonus?

In vanilla the args for object_event_append are always OLC_CRITTERS and the radius_target value from the spell entry.

I was unclear but I meant that in general.
 

As an Amazon Associate, rpgcodex.net earns from qualifying purchases.
Back
Top Bottom