Skip to content

GetIsDay Question

ZephiriusZephirius Member Posts: 411
edited July 2022 in Builders - Scripting
Trying to spawn a critter when entering an area, only if it is day time. I'm not seeing my spawn. When entering the game the clock is automatically set to 13:00 hours - daytime. Still no spawn.

Looked on the lexicon but didn't see anything informative...

Thanks for any help.
void main()
{
     object oPC = GetEnteringObject();
     if (GetIsPC(oPC)) return;

     location lLoc = GetLocation(GetWaypointByTag("ZUG_ZUG_LOC"));

     if (GetIsDay())
     {
     CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", lLoc);
     }
}
Post edited by Zephirius on

Comments

  • QuilistanQuilistan Member Posts: 177
    not sure if you have looked into spawn systems, but some of this is accomplished easily with them.

    NESS is one I have used for quite sometime:
    https://neverwintervault.org/project/nwn1/script/neshkes-extendable-spawning-system-ness-v813
  • TarotRedhandTarotRedhand Member Posts: 1,481
    edited July 2022
    If that is the actual script you are using the problem lies with your first if() (you missed out the ! before the GetIsPC(oPC)) -
    if  (GetIsPC(oPC))
    

    You are returning when it is the PC that is detected. Removing the 'return;' and instead adding a '{}' pair gives -
    void main()
    {
        object oPC = GetEnteringObject();
    
        if(GetIsPC(oPC))
        {   
            location lLoc = GetLocation(GetWaypointByTag("ZUG_ZUG_LOC"));
    
            if(GetIsDay())
            {
                CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", lLoc);
            }
        }
    }
    

    which, assuming everything else is correct, should work.

    TR
  • ProlericProleric Member Posts: 1,283
    Another problem is that the area OnEnter fires when you load a saved game. As it stands, another creature will be spawned every time you load during daytime.

    The simplest fix is to set a flag (local int) on the area when the creature spawns. If that's set, don't spawn another one.

    A more robust fix (which only needs coding once per module) is
    • On player enter, if the module has not been entered before, set a "module entered" flag, otherwise set a "loading saved game" flag on the PC
    • On area enter, if "loading saved game" is set, clear the flag and exit

    Triggers can also check the "loading saved game" flag, leaving it to the area to clear it (triggers fire first).

    Occasionally, there may be OnEnter actions that are required for both loads and normal entry - for example, scripted tweaks to sound / lighting. Do those before checking the flag, obviously.

    This is for SP - multiplayer might need a more sophisticated solution.
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Thanks guys. Great info.
    Yep, I missed the !
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Ok. I'll try to explain this as best I can, bear with me...

    The actors:

    Character 1. Strong Zug-Zug - impossible for a 1st level character to topple
    Character 2. Weak & Poisoned Zug-Zug

    Intententions for my really bad scripting...
    Only Spawn Strong Zug-Zug at night. If Strong Zug-Zug is poisoned only spawn weak Zug-Zug during day time. That's it.

    As it stands, the behavior of my code results in Strong Zug-Zug spawning during the day except when poisoned. What doesn't happen is weak Zug-Zug spawning in after Strong Zug-Zug is poisoned...
    void main()
    {
        object oTarget;
        object oSpawn;
    
        // Get the creature who triggered this event.
        object oPC = GetEnteringObject();
    
        // Only fire for (real) PCs.
        if ( !GetIsPC(oPC)  ||  GetIsDMPossessed(oPC) )
            return;
    
        // Only fire once per PC.
        if ( GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
            return;
        SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
    
        // If it is dawn or day or dusk.
        if ( GetIsDawn()  ||  GetIsDay()  ||  GetIsDusk() )
        {
            // Spawn Strong Zug-Zug.
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", GetLocation(oTarget));
        }
        else if (GetIsDay() && GetLocalInt(oPC, "weak_zugzug") == 1) // Refers to Zug-Zug's poisoning.
        {
            // Spawn weak & poisoned Zug-Zug if it's day
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug002", GetLocation(oTarget));
        }
    }
    

    Good Morning to all... :)
    Post edited by Zephirius on
  • TarotRedhandTarotRedhand Member Posts: 1,481
    Your description doesn't match your code. In your description you say that strong Zug Zug only appears at night but in your code it only appears when it is NOT night. Why?

    Try this in order to match your description -
    void main()
    {
        object oTarget;
        object oSpawn;
    
        // Get the creature who triggered this event.
        object oPC = GetEnteringObject();
    
        // Only fire for (real) PCs.
        if ( !GetIsPC(oPC)  ||  GetIsDMPossessed(oPC) )
            return;
    
        // Only fire once per PC.
        if ( GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
            return;
        SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
    
        // If it is night
        if(!(GetIsDawn() || GetIsDay() || GetIsDusk()))
        {
            // Spawn Strong Zug-Zug.
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", GetLocation(oTarget));
        }
        else if(GetIsDay() && GetLocalInt(oPC, "weak_zugzug")) // Refers to Zug-Zug's poisoning.
        {
            // Spawn weak & poisoned Zug-Zug if it's day
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug002", GetLocation(oTarget));
        }
    }
    

    One little thing. In C based languages like NwScript 1 == TRUE when used in an if() statement so there is no need to check for a local int being equal to one in that circumstance.

    TR
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    In my description I meant to write, strong Zug-Zug only appears during the day time hours. he's noctunal, and hunts at night. That's when we enter his cave and poison his drinking supply. Sorry for the confusion there. I think I was a little hasty. ;(
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Tried the script and it's spawing strong Zug-Zug at night? So the script needs attention to when and how he spawns, I think. I wan't him gone at night so we can posion the water during the day, so that we can fight weak Zug-Zug during the day. I hope that makes sense...
    Anyhow, thanks for the awsome help TarotRedhand and Proleric for the pointers...

    I'm gonna try to iron this script out. I think by now, ya'll know that is a dicey proposistion! :# Wish me luck. :/
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Everything works except weak Zug-Zug spawning at daytime so you can fight...

    Code I'm using right now...
    void main()
    {
        object oTarget;
        object oSpawn;
    
        // Get the creature who triggered this event.
        object oPC = GetEnteringObject();
    
        // Only fire for (real) PCs.
        if ( !GetIsPC(oPC)  ||  GetIsDMPossessed(oPC) )
            return;
    
        // Only fire once per PC.
        if ( GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
            return;
        SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
    
        // If it is dawn or day or dusk.
        if ( GetIsDawn()  ||  GetIsDay()  ||  GetIsDusk() )
        {
            // Spawn STRONG Zug-Zug the Hunter.
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", GetLocation(oTarget));
        }
        // Else, if it is day.
        else if ( GetIsDay() && GetLocalInt(oPC, "weak_zugzug"))
        {
            // Spawn WEAK Zug-Zug the Hunter/Poisoned
            oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug002", GetLocation(oTarget));
        }
    }
    

    Okee dokee. I throw in the proverbial towel! I'm tapping the mat! I'm crying uncle. I'm just crying... :'(:p
    P.S. I used Lilac Soul's script generator for most of the script...
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    What should the line of code look like for setting the poison Int from conversation node - mine looks like this:

    SetLocalInt(oPC, "weak_zugzug", 1);
    Then to call it - else if ( GetIsDay() && GetLocalInt(oPC, "weak_zugzug"))

    Don't know if that's correct?
    Post edited by Zephirius on
  • TarotRedhandTarotRedhand Member Posts: 1,481
    Try this version of your code
    void main()
    {
        object oTarget;
        object oSpawn;
    
        // Get the creature who triggered this event.
        object oPC = GetEnteringObject();
    
        // Only fire for (real) PCs.
        if ( !GetIsPC(oPC)  ||  GetIsDMPossessed(oPC) )
            return;
    
        // Only fire once per PC.
        if ( GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
            return;
        
        SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
        
        oTarget = GetWaypointByTag("ZUG_ZUG_LOC");
        
        // If it is day.
        
        if(GetIsDay() && GetLocalInt(oPC, "weak_zugzug")) 
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug002", GetLocation(oTarget)); // Spawn WEAK Zug-Zug the Hunter/Poisoned
        else if(!(GetIsNight())) // Otherwise, if it is dawn or day or dusk eg not Night.
            oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "bullywug004", GetLocation(oTarget)); // Spawn STRONG Zug-Zug the Hunter.
    }
    

    And let me know if the re-ordering of your code works.

    TR
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Hey Tarot,
    Yeah, I tried the code, but got the same result. No spawn of the weak version. Also, I'm waiting until 9 am before I even attempt to enter the cave - just to be sure it was day time. Wasn't exactly sure when day began. Although I would imagine arround 6 or 7.
    I've also triple checked the ResRefs and tags...
  • TarotRedhandTarotRedhand Member Posts: 1,481
    Wasn't exactly sure when day began. Although I would imagine around 6 or 7.

    Look in the module properties under the Advanced tab. It is defined in there.

    Experimenting in toolset (I have an idea). I may be sometime...

    TR
  • TarotRedhandTarotRedhand Member Posts: 1,481
    edited July 2022
    Having done a simple test (I added a test line where I set the local variable "weak_zugzug" to 1), I found that the above function works. Therefore the next logical place to look is the script where weak_zugzug is set. Can you post the whole of that script please and let me know which tab in the conversation for that node you are using.

    BTW, is it your intention that the PC only gets one chance to kill Zug Zug? That they can only enter the cave, with a chance of killing Zug Zug, once even if they do so at night? If not I can create a work around that let's the PC enter more than once.

    TR
  • ZephiriusZephirius Member Posts: 411
    edited July 2022
    Sorry for the delay.
    Yeah. I was trying for multiple chances.

    From the actions taken tab -
    void main()
    {
    
        object oPC = GetPCSpeaker();
        if (!GetIsPC(oPC)) return;
    
        SetLocalInt(oPC, "weak_zugzug", 1);
    
        object oZug = GetObjectByTag("ZUG_FX");
    
        location lLoc1 = GetLocation(GetWaypointByTag("BUBBLES_01"));
        location lLoc2 = GetLocation(GetWaypointByTag("BUBBLES_02"));
        location lLoc3 = GetLocation(GetWaypointByTag("GREEN_GLOW_LOC"));
    
        if (GetFirstItemInInventory(oPC) == GetObjectByTag("WUG_POISON"))
        {
            DestroyObject(GetObjectByTag("WUG_POISON"), 0.0);
            GetNextItemInInventory(oPC);
    
            CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_01", lLoc1);
            CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_02", lLoc2);
            CreateObject(OBJECT_TYPE_PLACEABLE, "tm_pl_invbarr001", lLoc3);
    
            DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect
            (VFX_FNF_WAIL_O_BANSHEES), oZug));
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect
            (VFX_FNF_GAS_EXPLOSION_ACID), oZug);
            DelayCommand(7.5, ActionSpeakString("His water has been amply corrupted!"));
        }
    }
    
    Post edited by Zephirius on
  • TarotRedhandTarotRedhand Member Posts: 1,481
    edited July 2022
    Sorry no, the problem isn't there either as far as "weak_zugzug" is concerned although there is a different potential problem with that code (see later). It would seem that "weak_zugzug" is being cleared elsewhere so you need to check your other scripts.

    Now onto the problem with the above code. You are assuming that the very first item in the PCs inventory is going to be the poison. This is not necessarily the case. Try the following version of your code with a little bit of editing.
    void main()
    {
        object oPC = GetPCSpeaker();
        object oPoison = GetObjectByTag("WUG_POISON");
        object oZug = GetObjectByTag("ZUG_FX");
        object oItem;
    
        location lLoc1 = GetLocation(GetWaypointByTag("BUBBLES_01"));
        location lLoc2 = GetLocation(GetWaypointByTag("BUBBLES_02"));
        location lLoc3 = GetLocation(GetWaypointByTag("GREEN_GLOW_LOC"));
    
        if(GetIsPC(oPC))
        {
            oItem = GetFirstItemInInventory(oPC);
    
            while(GetIsObjectValid(oItem))
            {
                if(oItem == oPoison)
                {
                    DestroyObject(GetObjectByTag("WUG_POISON"), 0.0);
                    GetNextItemInInventory(oPC);
    
                    CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_01", lLoc1);
                    CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_02", lLoc2);
                    CreateObject(OBJECT_TYPE_PLACEABLE, "tm_pl_invbarr001", lLoc3);
    
                    DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_WAIL_O_BANSHEES), oZug));
                    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_ACID), oZug);
                    DelayCommand(7.5, ActionSpeakString("His water has been amply corrupted!"));
                    break;
                }
    	    else
    		oItem = GetNextItemInInventory(oPC);
            }
            SetLocalInt(oPC, "weak_zugzug", 1);
        }
    }
    

    TR
  • ZephiriusZephirius Member Posts: 411
    Very nice form.

    Tried to no avail. I'll tear apart every script in the mod. Thankfully I'm just starting this one and the number of scripts is small. Even smaller yet would be the number of scripts germaine to the intended outcome.

    Thanks again TarotRedhand.

    I'll check back soon...
  • ZephiriusZephirius Member Posts: 411
    Oh I almost forgot...
    I had a qestion about the revised script above. When you use "while" are you creating a "loop", and that's why there is a "break" at the end? If not does it fry your game in an endless loop...

    The reason I ask is, when I've tried to use "while" before I always crash my game with code. I'm assuming it was because I didn't and don't know, how and when to "tie the knot" of the loop...?
    I don't know if that makes a bit of sense...? o:)
  • TarotRedhandTarotRedhand Member Posts: 1,481
    edited July 2022
    Yes it is a loop. The while says to repeat the following code as long as we have got a valid object. The if that follows tests for the presence of the poison. If the poison is found it does what is in the main body of the if(). At the end of that block of code, we exit the loop (break;). If the poison isn't found, the GetNextItemInInventory() gets the next item to test. This will repeat until either the poison is found or we run out of inventory items to test. When that happens oItem will contain an OBJECT_INVALID which will make the loop terminate.

    I explain all about loops (and other things) in the tutorial I wrote - "TR's Basics - Decisions". It's a 36 page pdf booklet that is extensively illustrated (eg loads of piccies). Give it a try. If you do get it, I highly recomend you use a dedicated pdf reading program as I went to the trouble of including bookmarks to make finding what you want easier.

    TR
  • ZephiriusZephirius Member Posts: 411
    I've downloaded your Tutorial. Very nicely done. I'll start taking some lessons soon...

    I looked at all of my scripts (all said and done about 20) and couldn't find anything that would cause any mayhem with the spawn that I could discern...
    Gonna pass a little time and start making my 2x2 mod in lesson #1 of your tutorial...
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    Alternatively, you could avoid scripting the loop yourself in this case, by simply using the GetItemPossessedBy() function. Not to further confuse you, but rather just to show another approach:
    void main()
    {
        object oPC = GetPCSpeaker();
        if (!GetIsPC(oPC)) return; //if the speaker is NOT(!) a player then end here
    
        object oZug = GetObjectByTag("ZUG_FX");
        location lLoc1 = GetLocation(GetWaypointByTag("BUBBLES_01"));
        location lLoc2 = GetLocation(GetWaypointByTag("BUBBLES_02"));
        location lLoc3 = GetLocation(GetWaypointByTag("GREEN_GLOW_LOC"));
        object oPoison = GetItemPossessedBy(oPC, "WUG_POISON");
    
        if (GetIsObjectValid(oPoison))
        {
            DestroyObject(oPoison, 0.0);
            CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_01", lLoc1);
            CreateObject(OBJECT_TYPE_PLACEABLE, "z_bubbles_02", lLoc2);
            CreateObject(OBJECT_TYPE_PLACEABLE, "tm_pl_invbarr001", lLoc3);
            DelayCommand(2.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_WAIL_O_BANSHEES), oZug));
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_ACID), oZug);
            DelayCommand(7.5, ActionSpeakString("His water has been amply corrupted!"));
            SetLocalInt(oPC, "weak_zugzug", 1);
        }
    }
    
  • ZephiriusZephirius Member Posts: 411
    Got ya. As someone who frequents these forums would say; "K.I.S.S." Keep it simple stupid.
  • 4BOLTMAIN4BOLTMAIN Member Posts: 90
    When I am looking for a local(int, string, etc.) in my module, I open one script, click the Find in Files button at the top of the script editor then I do this...

    ri9qfhk2269m.jpg

    Hope this helps.
  • TarotRedhandTarotRedhand Member Posts: 1,481
    2 very good items of advice guys.

    TR
  • ZephiriusZephirius Member Posts: 411
    Thanks 4BOLTMAIN! That's pretty handy.

    Would the fact that this script is being triggered as an area OnEnter script and not just a generic trigger have anything to do with weak ZUg-Zug not spawning? I wouldn't think so...?
  • 4BOLTMAIN4BOLTMAIN Member Posts: 90
    One thing I got confused with when I started scripting was trying to use the creatures tag to spawn it rather than the resref. I couldnt figure out why some worked but others didn't... turns out I assigned the creatures that worked the same tag as the resref...(ya, dont do that). So to check for a creature that exists already, use the creatures tag. To spawn a creature in an area make sure you are using the resref and not the tag. Your on_area_enter script for that area should work for what you are trying to accomplish. I am assuming the above code is the on enter script?
  • 4BOLTMAIN4BOLTMAIN Member Posts: 90
    edited July 2022
    Off topic, this concept really reminds me of Styx, poisoning the guards food... except they die, lol.
  • ZephiriusZephirius Member Posts: 411
    Zug-Styx... lol >:)
Sign In or Register to comment.