Temple+ Modding Question

Discussion in 'General Modification' started by _doug_, Feb 21, 2018.

Remove all ads!
  1. Sagenlicht

    Sagenlicht Established Member

    Joined:
    Apr 14, 2004
    Messages:
    193
    Likes Received:
    39
    I don't think so Endarire and I don't think they are really needed. I am fully aware what's the difference between a swift and an immediate action is. Feather Fall NEEDS this rule but that's not relevant for ToEE. And only a VERY limited amount of other spells actually are immediate actions.
     
  2. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    Heads up for modders: as of next version, you should be able to extend any .mes file (i.e. without completely overriding existing ones). This is to minimize impact on non-english versions, and also to improve modularity.

    See https://github.com/GrognardsFromHell/TemplePlus/wiki/Files for more info.

    I haven't thoroughly tested it yet so let me know if any issues come up.
     
    Sagenlicht and anatoliy like this.
  3. anatoliy

    anatoliy Established Member

    Joined:
    Feb 18, 2017
    Messages:
    518
    Likes Received:
    136
    @Sitra Achara
    Will you support previous conventions like description/*.mes ?
    Or should it be description_ext/*.mes ?

     
  4. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    I haven't removed those but I'd like to move to the new system, at least for files distributed along with Temple+ itself.
     
  5. Sagenlicht

    Sagenlicht Established Member

    Joined:
    Apr 14, 2004
    Messages:
    193
    Likes Received:
    39
    Will test today evening :)
     
  6. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    No need actually, it's definitely bugged.

    Will fix later, master is kinda broken now :rolleyes:
     
  7. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    Ok should work now.
     
  8. Endarire

    Endarire Ronald Rynnwrathi

    Joined:
    Jan 7, 2004
    Messages:
    819
    Likes Received:
    83
    @Sitra Achara
    Greetings, Sitra! I posted this last week on the RPGCodex forum but got no reply.

    Practiced Spellcaster (Divine) on a multiclass Cleric also gives domain bonus spell slots but no higher level spells. (Thus, a Cleric1/Wizard8 with Practiced Spellcaster (Divine) has level 1-3 domain slots due to the feat but only level 1 domain spells known.) Since domain spells are divine spells, I was disappointed when I couldn't use this trick for early entry into Mystic Theurge (Cleric1/arcane caster 3 or 4/MT afterward). There was

    Domain spells also seemingly don't work with metamagic. I tried applying Extend Spell to a domain spell and got a blank space with a "+Apply Metamagic" effect.

    I used Co8 NC, T+, ShiningTed's domain spells mod, IcyDemon's textures mod, and other mods that shouldn't mechanically matter.

    Saves.

    Enjoy!
     
  9. Sagenlicht

    Sagenlicht Established Member

    Joined:
    Apr 14, 2004
    Messages:
    193
    Likes Received:
    39
    This might be a dumb question, but why does attachee.inventory_item(4) return OBJ_HANDLE_NULL instead of the weapon in the primary slot?
     
  10. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    That's because worn items start at 200. The usual method to access those is with .item_worn_at.
     
  11. Sagenlicht

    Sagenlicht Established Member

    Joined:
    Apr 14, 2004
    Messages:
    193
    Likes Received:
    39
    Ok, my bad for asking a very unspecific question.

    I tried to get the item so I can use item_condition_remove on it.

    I tried attachee.inventory_item(args.get_arg(2)) but it returns OBJ_HANDLE_NULL

    So I tried inventory_item(x) with x as 3, 4, 203 and 204, all returned OBJ_HANDLE_NULL, which in return led me believe I am using the function with an incorrect syntax and led me to the above badly worded question.

    In the end, I need to get the item that is stored in args.get_arg(2)
     
  12. Sitra Achara

    Sitra Achara Senior Member

    Joined:
    Sep 1, 2003
    Messages:
    3,375
    Likes Received:
    366
    Just to be sure, attachee is the wielder? Or could it be the item?
     
  13. dolio

    dolio Established Member Supporter

    Joined:
    May 30, 2005
    Messages:
    312
    Likes Received:
    59
    I don't think you should need to be looking around in the inventory to remove the condition (which won't work in general anyway).

    The way it's set up for e.g. Magic Weapon, what you do is first do `condition_add('sp-Magic Weapon')` to the item, which adds a condition that applies to the item. Then the OnAdd trigger for that condition does `item_condition_add(..)` which applies the conditions that need to go on the creature holding the weapon. Then, when the first thing expires, it runs a callback that gets the item as the 'attachee' (and the spell id as an arg), and you can then call `item_condition_remove` there.

    If you want to keep targeting creatures with the spell, you should still apply the first spell condition directly to the object (by using e.g. `target.item_worn_at(...).condition_add_with_args(...)`) for this reason.

    Oh, and the reason looking through inventories won't work is that the weapon may no longer be in the original target's inventory when the spell expires.
     
  14. Sagenlicht

    Sagenlicht Established Member

    Joined:
    Apr 14, 2004
    Messages:
    193
    Likes Received:
    39
    @Sitra Achara
    Its the wielder, I verified that via a debug print.

    @dolio
    I am unsure I can follow your thougts. If you enchant an item via mainhandWeapon.item_condition_add('weapon Sonic', 0, 0, 0, 0, spell_id) and then move the item from the original spell target to another inventory and equip it to that party member, the following debug print on attachee returns the new party member.

    This is the updated Sonic Weapon condition.py:
    Code:
    def verifyItem(item, args):
        item_loc = item.obj_get_int(obj_f_item_inv_location)
        target_loc = args.get_arg(2)
        return item_loc == target_loc
    
    def sonicWeaponSpellAddWeaponCondition(attachee, args, evt_obj):
        mainhandWeapon = attachee.item_worn_at(item_wear_weapon_primary)
        mainhandWeapon.item_condition_add_with_args('Weapon Sonic', 0, 0, 0, 0, args.get_arg(0))
        return 0
    
    sonicWeaponSpell = PythonModifier("sp-Sonic Weapon", 3) # spell_id, duration, empty
    sonicWeaponSpell.AddHook(ET_OnConditionAdd, EK_NONE, sonicWeaponSpellAddWeaponCondition,())
    sonicWeaponSpell.AddHook(ET_OnD20Query, EK_Q_Critter_Has_Spell_Active, spell_utils.queryActiveSpell, ())
    sonicWeaponSpell.AddHook(ET_OnD20Signal, EK_S_Killed, spell_utils.spellKilled, ())
    sonicWeaponSpell.AddSpellDispelCheckStandard()
    sonicWeaponSpell.AddSpellTeleportPrepareStandard()
    sonicWeaponSpell.AddSpellTeleportReconnectStandard()
    sonicWeaponSpell.AddSpellCountdownStandardHook()
    
    #### Weapon Sonic Condition ####
    
    def weaponSonicOnDealingDamage(attachee, args, evt_obj):
        usedWeapon = evt_obj.attack_packet.get_weapon_used()
        if not verifyItem(usedWeapon, args):
            return 0
        damageDice = dice_new('1d6') #Sonic Weapon Bonus Damage
        damageType = D20DT_SONIC
        damageMesId = 3001 #ID 3001 added in damage.mes
        evt_obj.damage_packet.add_dice(damageDice, damageType, damageMesId)
        return 0
    
    def weaponSonicGlowType(attachee, args, evt_obj):
        usedWeapon = evt_obj.get_obj_from_args()
        if verifyItem(usedWeapon, args):
            if not evt_obj.return_val:
                evt_obj.return_val = 7 #there is no sonic Weapon Glow in the game I think using holy for now
        return 0
    
    def weaponSonicRemoveCondition(attachee, args, evt_obj):
        print "Debug Remove Item Condition"
        print "Debug args.get_arg(2): {}".format(args.get_arg(2))
        print "Debug attachee: {}".format(attachee)
        enchantedWeapon = attachee.inventory_item(args.get_arg(2))
        print "Debug enchantedWeapon: {}".format(enchantedWeapon) #returns OBJ_HANDLE_NULL
        #enchantedWeapon.item_condition_remove('Weapon Sonic', args.get_arg(4)) #Does not work
        return 0
    
    weaponSonic = PythonModifier("Weapon Sonic", 5) # bonusValue, arg2, inventory_idx, arg4, spell_id
    weaponSonic.AddHook(ET_OnDealingDamage, EK_NONE, weaponSonicOnDealingDamage, ())
    weaponSonic.AddHook(ET_OnWeaponGlowType, EK_NONE, weaponSonicGlowType, ())
    weaponSonic.AddHook(ET_OnD20Signal, EK_S_Spell_End, weaponSonicRemoveCondition, ())
    
    I would like to cast the spell not directly on the item but on the wielder due to mass spells like align weapon, mass which would be hard to hanlde otherwise. In adition its quicker if you simply target a party member instead of an item in your inventory.
     
  15. dolio

    dolio Established Member Supporter

    Joined:
    May 30, 2005
    Messages:
    312
    Likes Received:
    59
    @Sagenlicht My suggestion is basically like this.

    You make two conditions. One is 'sp-Sonic Weapon', one is 'Weapon Sonic'. The latter is what you have now, and the first one is just used for tracking the spell targeting/duration.

    In the spell script (either normal or mass), you call:

    Code:
    weapon = target_item.obj.item_worn_at(item_wear_weapon_primary)
    weapon.condition_add_with_args(
        'sp-Sonic Weapon', spell.id, spell.duration, ...)
    This adds a condition that targets the item to track the spell's duration on it.

    The 'sp-Sonic Weapon' condition should have at least two hooks. In OnConditionAdd, you do:

    Code:
    def Add(weapon, args, evt_obj):
      weapon.item_condition_add_with_args(
        'Weapon Sonic', 0, 0, 0, 0, args.get_arg(0))
      return 0
    
    This adds the condition that applies to whoever holds the weapon. In OnConditionRemove, you do:

    Code:
    def Remove(weapon, args, evt_obj):
      weapon.item_condition_remove('Weapon Sonic', args.get_arg(0))
      return 0
    
    This means that whenever the 'sp-Sonic Weapon' expires (or gets dispelled or whatever), the related item condition gets removed from that weapon. The relevant item gets passed directly to the callback, because it's a condition affecting the object.

    My Disrupting Weapon implementation works this way if you want to look at an actual example.
     
Our Host!