Skip to content

Timestop portrait

arvutarvut Member Posts: 10
I've written an override for the timestop spell, which freezes, paralyzes and immobilizes (all done with the cutscreen functions) every creature in the area.

The latest addition to this script I've tinkered with is the change of the portrait of whoever is affected by it.
I'm trying to change the portrait to the actual Time Stop portrait used in the game, but this is nowhere to be found in 2da's or anywhere else. Hence it must be hardcoded into the engine itself for use when EffectTimeStop(); is called. The Portrait overhaul project on https://nwn.wiki/display/NWNOP/Overhaul+Portraits mentions "po_timestop", however when calling this via the SetPortraitResRef function you end up with the Null Human (Default) portrait instead.

Here's the code, any ideas on how to set the timestop portrait is welcome. Feel free to use the code as you like.
//::///////////////////////////////////////////////
//:: Time Stop
//:: NW_S0_TimeStop.nss
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    All persons in the Area are frozen in time
    except the caster.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Jan 7, 2002
//:://////////////////////////////////////////////

#include "x2_inc_spellhook"

void main()
{

/*
  Spellcast Hook Code
  Added 2003-06-20 by Georg
  If you want to make changes to all spells,
  check x2_inc_spellhook.nss to find out more

*/

    if (!X2PreSpellCastCode())
    {
    // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
        return;
    }

// End of Spell Cast Hook


    //Declare major variables
    location lTarget = GetSpellTargetLocation();
    effect eVis = EffectVisualEffect(VFX_FNF_TIME_STOP);
    effect ePara = EffectCutsceneParalyze();
    effect eImob = EffectCutsceneImmobilize();
    effect eFreeze = EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION);
    object oCaster = OBJECT_SELF;
    object oTarget;
    object oArea = GetArea(oCaster);
    string sPortrait;

    //Fire cast spell at event for the specified target
    SignalEvent(OBJECT_SELF, EventSpellCastAt(OBJECT_SELF, SPELL_TIME_STOP, FALSE));
    ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTarget);
    //Apply the VFX impact and effects
    oTarget = GetFirstObjectInArea(oArea);
    while (GetIsObjectValid(oTarget))
    {
        if (oTarget != oCaster)
        {
            sPortrait = GetPortraitResRef(oTarget);
            SetLocalString(oTarget, "PORTRAIT", sPortrait);
            SetPortraitResRef(oTarget, "po_timestop");
            DelayCommand(0.50, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFreeze, oTarget, 12.0));
            DelayCommand(0.50, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePara, oTarget, 12.0));
            DelayCommand(0.50, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eImob, oTarget, 12.0));
            DelayCommand(12.0, SetPortraitResRef(oTarget, GetLocalString(oTarget, "PORTRAIT")));
        }
        oTarget = GetNextObjectInArea(oArea);
    }
}

Comments

  • ForSeriousForSerious Member Posts: 508
    I've been meaning to do this for quite some time. Any reason why 12 second duration instead of 9?
    I'll take a look with the resource extractor I have, maybe I can find the portrait.
  • arvutarvut Member Posts: 10
    Cool, would be sweet to have this, as it almost completes the timestop effect without making it module-wide. The 12s duration is subjective, the PW this applies to has a long list of buffed spells, timestop might even get a duration overhaul with spellfocus feats in the future.
  • ForSeriousForSerious Member Posts: 508
    No dice. po_timestop is applied like the po_pasue portrait. Like, while the game is paused or level up, if you type in chat, you still have your original portrait.
    I know for sure that you can get it to work with nwnx, because I played for years on a server that did it. I don't know anything about how to use nwnx though.
    The best I got was to change to a unused portrait like po_btlbomb_. It's a hand-drawn TEMP. Looks tacky, but you could find something else.
    My other idea was to add a line to the portraits.2da then use SetPortraitId(). I haven't tried that yet. It might end with the same results.
  • ForSeriousForSerious Member Posts: 508
    Here's another idea. Give everyone EffectTimeStopImmunity, then in the timestop spell, take off the immunity and apply the built-in effect. How much will the mess up timers all around the server?
  • arvutarvut Member Posts: 10
    Hmmm, I guess the idea of timestop immunity could work. I'm not an expert on nwnx either but we have it running for PW bank and player location.

    However if the EffectTimeStopImmunity is applied globally, wouldn't that also not apply the timestop portrait? As for timers, not sure if it would change much, since noone is affected by it other than the module clock.

    We had a weird bug in 1.69 where time stood still upon module load, when EffectTimestop was cast as per unmodified bioware spell, the clock would skip to the current time, affecting daylight and timestap on compass. This isn't a problem in NWN:EE though.
  • ForSeriousForSerious Member Posts: 508
    edited February 5
    You are missing:
    effect eShow = EffectIcon(EFFECT_ICON_TIMESTOP);
    DelayCommand(0.50, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eShow, OBJECT_SELF, 12.0f));
    
    It gives the little spell icon status. It's meant to be for the caster, but you could add it to everyone effected to indicate what's going on instead of changing the portraits.

    Giving the global immunity should work like normal for those that get the immunity removed for the duration of the spell.
    I'm imagining adding the immunity in the main when a player first joins script, and in all the onspawn scripts.
  • ForSeriousForSerious Member Posts: 508
    Okay. I made a version of the spell with the 'everyone's immune' approach. The only side effect is that players outside of the area of effect get the timestop portrait for random amounts of time when it's cast. Also visual effects pause while the portrait is showing.
  • arvutarvut Member Posts: 10
    Well, that kinda defeats the purpose of having the portrait. If you're not affected by the actual timestop (which is area only) but still get the portrait. I guess I'll have to drop the idea of this, it's only cosmetic anyway and the spell works as intended apart from that.
  • arvutarvut Member Posts: 10
    I think giving every creature and PC the timestop immunity in all other areas than the area it's cast at would result in a pretty decent outcome and then using the actual EffectTimeStop(), but that would create a lot of overhead for the server to deal with.
  • ForSeriousForSerious Member Posts: 508
    My test was an NPC casting Time stop on heartbeat. Usually the portrait just flashed. But there were times when it seemed to get stuck for long amounts of time. Probably because timestop lasts longer than the heartbeat. I figured that simulates a full-ish server pretty well.

    I'm (still) disappointed in how hard it is to work with Time Stop.
  • arvutarvut Member Posts: 10
    Thanks for testing, my tests includes a hostile npc that casts the spell when it perceives a player. You could also call the script from a conversation with an npc for more controlled testing, calling the function on a npc in another area to cast it. if you cast in onHeartbeat instead then perhaps lower the duration to 3-4 seconds?
Sign In or Register to comment.