Skip to content

Mimic Script Help

I'm trying to make a respawning Mimic. Here's my idea:
1. Player opens a placeable chest.
2. Random chance the chest will disappear and a Mimic will spawn.
3. After the chest disappears, it will respawn after a set amount of time.

This is the script I got so far:
//** Mimic test
//Put this script OnOpen
#include "nw_i0_generic"
void main()
{

object oPC = GetLastOpenedBy();

if (!GetIsPC(oPC)) return;

object oTarget;
oTarget = GetObjectByTag("MIMIC_PLC_SPAWNER_001");

//Visual effects can't be applied to waypoints, so if it is a WP
//the VFX will be applied to the WP's location instead

int nInt;
nInt = GetObjectType(oTarget);

if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM), oTarget);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM), GetLocation(oTarget));

DestroyObject(oTarget, 3.0);

object oSpawn;
location lTarget;
oTarget = oPC;

lTarget = GetLocation(oTarget);

oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "mimic_basic_001", lTarget);

oTarget = oSpawn;

SetIsTemporaryEnemy(oPC, oTarget);

AssignCommand(oTarget, ActionAttack(oPC));

AssignCommand(oTarget, DetermineCombatRound(oPC));

oTarget = GetWaypointByTag("MIMIC_SPAWN_TEST_001");

lTarget = GetLocation(oTarget);

oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "mimic_plc_spawne", lTarget);

oTarget = oSpawn;

//Visual effects can't be applied to waypoints, so if it is a WP
//the VFX will be applied to the WP's location instead

nInt = GetObjectType(oTarget);

if (nInt != OBJECT_TYPE_WAYPOINT) DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_BLOOD_SPARK_LARGE), oTarget));
else DelayCommand(0.5, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_BLOOD_SPARK_LARGE), GetLocation(oTarget)));

}

I tried adding a delay, but it broke the script. This does a basic function of removing the opened chest, spawning a Mimic creature, and respawning the chest. Rinse and repeat. But.. I need the chest to respawn after a longer period of time. Right now it respawns almost instantly. I'd like it to respawn about 5 minutes later or so, instead of instantly.

Also (about these forums), how do I make those cool windows that you can put code in?

Comments

  • NeverwinterWightsNeverwinterWights Member Posts: 339
    edited February 2022
    Can do something like so:
    #include "nw_i0_generic"
    //To delay the creation of a placeable you need to make a function
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
        SendMessageToPC(GetFirstPC(), "New chest should be spawning now.");
    }
    
    void main()
    {
        object oPC = GetLastOpenedBy();
        if (!GetIsPC(oPC)) return;
    
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);//just use the location of the chest you are opening. No waypoints needed.
        int iRandom = Random(10);//Random number used to check mimic spawn, 1 in 10 chance. Can change to whatever.
        effect eChunk = EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM);
    
        if (iRandom == 0)//1 in 10 chance
        {
            ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eChunk, lLoc);
            object oMimic = CreateObject(OBJECT_TYPE_CREATURE, "mimic_basic_001", lLoc);
            AssignCommand(oMimic, DetermineCombatRound(oPC));
        }
        AssignCommand(GetModule(), DelayCommand(300.0, RespawnSelf(sResRef, lLoc)));//the module will respawn self(chest) after 5 mins
        DestroyObject(OBJECT_SELF, 0.5);
    }
    

    I put some commentary in there to try and explain some things. Hope it helps.

    P.S. To put script in a separate window type [ code ] at the beginning and type [ /code ] at the end, without the spaces between the brackets and the letters.
  • Ugly_DuckUgly_Duck Member Posts: 182
    edited February 2022
    This works great, thanks! How do I make the regular, non-mimic placeables spawn treasure, and stay open long enough for the player to loot them? Right now the non-mimic placeables open, then close in like 1 second. I'd like the non-mimic placeables to stay open until they're Closed by the player. Thanks again!
  • Ugly_DuckUgly_Duck Member Posts: 182
    Also, when the player destroys the placeable (weapon, spell, etc), nothing spawns back.
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    Ugly_Duck wrote: »
    This works great, thanks! How do I make the regular, non-mimic placeables spawn treasure, and stay open long enough for the player to loot them? Right now the non-mimic placeables open, then close in like 1 second. I'd like the non-mimic placeables to stay open until they're Closed by the player. Thanks again!

    If you want it to act like a regular chest if it's not a mimic, then you might do something like so:
    #include "nw_i0_generic"
    //To delay the creation of a placeable you need to make a function
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        object oPC = GetLastOpenedBy();
        if (!GetIsPC(oPC)) return;
    
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);//just use the location of the chest you are opening. No waypoints needed.
        int iRandom = Random(10);//Random number used to check mimic spawn, 1 in 10 chance. Can change to whatever.
        effect eChunk = EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM);
    
        if (iRandom == 0)//1 in 10 chance it's a mimic
        {
            //If it's a mimic, all this stuff will happen
            ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eChunk, lLoc);
            object oMimic = CreateObject(OBJECT_TYPE_CREATURE, "mimic_basic_001", lLoc);
            AssignCommand(oMimic, DetermineCombatRound(oPC));
            AssignCommand(GetModule(), DelayCommand(300.0, RespawnSelf(sResRef, lLoc)));//the module will respawn self(chest) after 5 mins
            DestroyObject(OBJECT_SELF, 0.5);
        }
        else //if not a mimic then regular chest
        {
            ExecuteScript("x2_02_low", OBJECT_SELF);//x2_02_low is a standard NWN low treasure scritp. Can change to whatever.
        }
    
    }
    

    This is just basic. There is a lot of nuance involved depending on how you want it to work. Is this going to be a single player module or multiplayer? If multiplayer does everyone get to open it or is it a one time thing (DoOnce) until reset? Do you want the chest to respawn if a player smashes it or does it stay destroyed? Do you want the chest to destroy itself when the player closes the chest? What if the same player opens the chest and it's a "regular" chest and then opens and closes it until it's a mimic (DoOnce per player?)? Does the chest need to decide (random number) OnSpawn rather than OnOpen if it is a mimic, to make everything else function correctly? Etc, etc...
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    Ugly_Duck wrote: »
    Also, when the player destroys the placeable (weapon, spell, etc), nothing spawns back.

    Again there may be some nuance involved. You could also add an execute script line for another one of those NWN default treasure spawn scripts if you want it to act like a regular placeable/chest if it's bashed in addition to it respawning. Something like this could work for a simple placeable respawn script in the OnDeath event:
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);
        AssignCommand(GetModule(), DelayCommand(30.0, RespawnSelf(sResRef, lLoc)));
    }
    
  • Ugly_DuckUgly_Duck Member Posts: 182
    it seems to do well spawning treasure on non-mimic chests. Only issues are after a non-mimic chest gets looted, then closed, they don't despawn and respawn later (30 seconds just for testing purpose). Also, if they're bashed before opened, mimic or non-mimic, nothing spawns back. This is what I got (all your code. I just copied it):
    // Goes "OnOpen"
    #include "nw_i0_generic"
    //To delay the creation of a placeable you need to make a function
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
        SendMessageToPC(GetFirstPC(), "New chest should be spawning now.");
    }
    
    void main()
    {
        object oPC = GetLastOpenedBy();
        if (!GetIsPC(oPC)) return;
    
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);//just use the location of the chest you are opening. No waypoints needed.
        int iRandom = Random(3);//Random number used to check mimic spawn, 1 in 10 chance. Can change to whatever.
        effect eChunk = EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM);
    
        if (iRandom == 2)//1 in 10 chance
        {
            ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eChunk, lLoc);
            object oMimic = CreateObject(OBJECT_TYPE_CREATURE, "mimic_basic_001", lLoc);
            AssignCommand(oMimic, DetermineCombatRound(oPC));
    
        AssignCommand(GetModule(), DelayCommand(15.0, RespawnSelf(sResRef, lLoc)));//the module will respawn self(chest) after 5 mins
        DestroyObject(OBJECT_SELF, 0.5);
           }
        else //if not a mimic then regular chest
        {
            ExecuteScript("x2_02_low", OBJECT_SELF);//x2_02_low is a standard NWN low treasure scritp. Can change to whatever.
        }
    }
    

    This is gonna be a multi-player module.
    1.) Chests only give items to the PC opening/looting the chest.
    2.) After the PC closes the placeable, it despawns then respawns back after set amount of time; with the chance of being a mimic again.

    Thanks for taking the time to help me.
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    edited February 2022
    As far as the chest despawning and later respawning when closed, you could put something like this in the OnClosed event:
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);
        AssignCommand(GetModule(), DelayCommand(30.0, RespawnSelf(sResRef, lLoc)));
        DestroyObject(OBJECT_SELF, 0.5);
    }
    

    As for bashing the chest and destroying it, something like so in the OnDeath event:
    
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);
        ExecuteScript("x2_02_low", OBJECT_SELF);
        AssignCommand(GetModule(), DelayCommand(30.0, RespawnSelf(sResRef, lLoc)));
        //PS As is, if someone bashes the chest and destroys it, it won't have a chance to spawn a mimic but will just act like destroying a regular chest. 
    }
    

    As far as only one player being able to loot it, well that gets a little complicated. The only way I know how to do it for sure is to make the chest sort of a pretend chest and instead of it actually having inventory, you make it spawn in an invisible object with the real inventory that you would script the player to interact with. You then need to add an OnClosed to that invisible object that destroys the fake chest, which would require a completely different OnOpen script, yada yada yada. Basically similar to shared loot chests and persistent item chest systems which can get a bit messy and complicated. At least as far as I know. I've never been able to successfully stop a player from using/opening a chest while another player is currently using it (without scripting the above mentioned method), as there are 2 events tied to it. OnUsed and OnClicked. The OnUsed from the radial menu can bypass the OnClicked. Unless someone else knows how or knows something I'm missing.
  • Ugly_DuckUgly_Duck Member Posts: 182
    Wow I screwed this whole thing up lol. I got this in the OnClose event:
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);
        AssignCommand(GetModule(), DelayCommand(30.0, RespawnSelf(sResRef, lLoc)));
        DestroyObject(OBJECT_SELF, 0.5);
    }
    
    And, I got this in the OnDeath:
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);
        ExecuteScript("x2_02_low", OBJECT_SELF);
        AssignCommand(GetModule(), DelayCommand(30.0, RespawnSelf(sResRef, lLoc)));
        //PS As is, if someone bashes the chest and destroys it, it won't have a chance to spawn a mimic but will just act like destroying a regular chest. 
    }
    
    These both work fine. I don't know what I did, but I can't get the mimic to spawn now. This is what I have for the mimic code:
    #include "nw_i0_generic"
    //To delay the creation of a placeable you need to make a function
    void RespawnSelf(string sResRef, location lLoc)
    {
        CreateObject(OBJECT_TYPE_PLACEABLE, sResRef, lLoc);
    }
    
    void main()
    {
        object oPC = GetLastOpenedBy();
        if (!GetIsPC(oPC)) return;
    
        string sResRef = GetResRef(OBJECT_SELF);
        location lLoc = GetLocation(OBJECT_SELF);//just use the location of the chest you are opening. No waypoints needed.
        int iRandom = Random(10);//Random number used to check mimic spawn, 1 in 10 chance. Can change to whatever.
        effect eChunk = EffectVisualEffect(VFX_COM_CHUNK_BONE_MEDIUM);
    
        if (iRandom == 0)//1 in 10 chance it's a mimic
        {
            //If it's a mimic, all this stuff will happen
            ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eChunk, lLoc);
            object oMimic = CreateObject(OBJECT_TYPE_CREATURE, "mimic_basic_001", lLoc);
            AssignCommand(oMimic, DetermineCombatRound(oPC));
            AssignCommand(GetModule(), DelayCommand(10.0, RespawnSelf(sResRef, lLoc)));//the module will respawn self(chest) after 5 mins
            DestroyObject(OBJECT_SELF, 0.5);
        }
        else //if not a mimic then regular chest
        {
            ExecuteScript("x2_02_low", OBJECT_SELF);//x2_02_low is a standard NWN low treasure scritp. Can change to whatever.
        }
    
    }
    
    Again I appreciate all the help. But, I cannot figure this out. What am I doing wrong here?
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    edited March 2022
    Hmm. Using exactly what you posted there for the 3rd script, it's working fine for me in testing. Double check that these scripts are on the actual blueprint chest and not just the chest that is already placed in the module (that 3rd one in the OnOpen event). Sometimes I forget that I add a script to a placeable object for testing but not it's blueprint. So when it gets respawned using the resref, it's not going to have the right scripts in the right places.
  • Ugly_DuckUgly_Duck Member Posts: 182
    Thanks so much! That is what I was doing wrong. Didn't have the last script in the palette. It works just fine now. Thanks again folks!
  • ZephiriusZephirius Member Posts: 411
    Yeah, thanks from me too! I was looking for something like this.
  • Ugly_DuckUgly_Duck Member Posts: 182
    Zephirius wrote: »
    Yeah, thanks from me too! I was looking for something like this.

    These guys are the best!
  • ZephiriusZephirius Member Posts: 411
    These guys are the best!

    I would have to agree wholeheartedly! They don't have to take the time to bail us out, but they do!
    //To delay the creation of a placeable you need to make a function

    Is this true? - I've become accustomed to using CreateObjectVoid() with the #include file ""nw_i0_2q4luskan"
  • meaglynmeaglyn Member Posts: 149
    edited March 2022
    That is a function. If you make your own you don't have to include that file which has a lot of plot specific code you don't need. But that will work too.
    Edit: I suppose for clarity we should add the word "wrapper" before "function" in both my answer and the comment you quoted...
    Post edited by meaglyn on
Sign In or Register to comment.