Level One rework

Revamped Level One: North & Level One: Central to be as close to PnP as possible.  Added Level One: Latrene 3 area.  Added efreeti appearance from CEP3.  Revamped efreeti bottle to be like PnP (no wishes, yet)
This commit is contained in:
Jaysyn904
2023-09-23 22:02:32 -04:00
parent 7832a55868
commit 2e30722043
106 changed files with 40744 additions and 9332 deletions

View File

@@ -0,0 +1,83 @@
//:: at_dm_attack1.nss
//::
//:: Spawns the Dung Monster (ra_dungmonster01) from the Commode conversation.
//::
//::
void main()
{
//:: Declare major variables
object oPlaceable = OBJECT_SELF;
//:: Check if the Dung Monster is already active
int DungMonsterActive = GetLocalInt(GetModule(), "DungMonsterActive");
//:: If it's not already active, spawn the Dung Monster
if (DungMonsterActive == 0)
{
object oCreature = GetObjectByTag("ra_dungmonster01");
// Check if the monster already exists
if (!GetIsObjectValid(oCreature))
{
// If it doesn't exist, spawn it
oCreature = CreateObject(OBJECT_TYPE_CREATURE, "ra_dungmonster01", GetLocation(oPlaceable));
// Get the nearest player to the placeable
object oNearestPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oPlaceable);
// If we found a player, make the creature attack them
if (GetIsObjectValid(oCreature) && GetIsObjectValid(oNearestPlayer))
{
AssignCommand(oCreature, ActionAttack(oNearestPlayer));
}
}
// Set the Dung Monster as active in the module
SetLocalInt(GetModule(), "DungMonsterActive", 1);
}
//:: Clear the plot flag on the commode
SetPlotFlag(oPlaceable, FALSE);
//:: Destroy the commode
DestroyObject(oPlaceable, 0.0f);
//:: Spawn the latrine hole
object oHole = CreateObject(OBJECT_TYPE_PLACEABLE, "ra_plc_dm_hole", GetLocation(oPlaceable));
}
/* void main()
{
//:: Declare major variables
object oPlaceable = OBJECT_SELF;
//:: Spawn the Dung Monster
object oCreature = CreateObject(OBJECT_TYPE_CREATURE, "ra_dungmonster01", GetLocation(oPlaceable));
//:: Get the nearest player to the placeable
object oNearestPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oPlaceable);
//:: If we found a player, make the creature attack them
GetIsObjectValid(oCreature) && GetIsObjectValid(oNearestPlayer))
{
AssignCommand(oCreature, ActionAttack(oNearestPlayer));
}
//:: Clear the plot flag on the commode
SetPlotFlag(oPlaceable, FALSE);
//:: Set a var on the module to show the Dung Monster is active
SetLocalInt(GetModule(), "DungMonsterActive", TRUE);
//:: Destroy the commode
DestroyObject(oPlaceable, 0.0f);
//:: Spawn the latrene hole
object oHole = CreateObject(OBJECT_TYPE_PLACEABLE, "ra_plc_dm_hole", GetLocation(oPlaceable));
} */

View File

@@ -0,0 +1,14 @@
void main()
{
object oTarget;
// Get the PC who is in this conversation.
object oPC = GetPCSpeaker();
// Find the location to which to teleport.
oTarget = GetWaypointByTag("WP_LATRENE3");
// Teleport the PC.
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, JumpToObject(oTarget));
}

View File

@@ -34,12 +34,13 @@ if(GetLocalInt(oClicker,"DoorOnce") == FALSE)
DelayCommand(1.1,DeleteLocalInt(oClicker,"DoorOnce"));
//:: Prevents the Dung Monster from perma-chasing PC's
//:: Prevents the Dung Monster from perma-chasing PC's
int nRandom = d4(1);
if (sResRef == "ra_dungmonster" && nRandom > 2)
{
DestroyObject(oClicker);
DelayCommand(0.0f, SetLocalInt(GetModule(), "DungMonsterActive", FALSE));
}
if(GetIsPC(oClicker)==TRUE)

View File

@@ -0,0 +1,45 @@
//::///////////////////////////////////////////////
//:: Name x2_def_heartbeat
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Gelatinous Cube Heartbeat
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: Sept 16/03
//:://////////////////////////////////////////////
#include "x0_i0_spells"
#include "x2_i0_spells"
void main()
{
// execute default AI
ExecuteScript("nw_c2_default1", OBJECT_SELF);
// Cube additions
// * Only on the first heartbeat, destroy the creature's personal space
if (!GetLocalInt(OBJECT_SELF,"X2_L_GCUBE_SETUP"))
{
effect eGhost = EffectCutsceneGhost();
eGhost = SupernaturalEffect(eGhost);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eGhost,OBJECT_SELF);
SetLocalInt(OBJECT_SELF,"X2_L_GCUBE_SETUP",TRUE) ;
}
object oVictim = GetFirstObjectInShape(SHAPE_CUBE,4.0f,GetLocation(OBJECT_SELF),TRUE, OBJECT_TYPE_CREATURE);
while (GetIsObjectValid(oVictim))
{
if (spellsIsTarget(oVictim,SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF) && oVictim != OBJECT_SELF)
{
EngulfAndDamage(oVictim,OBJECT_SELF);
}
oVictim = GetNextObjectInShape(SHAPE_CUBE,4.0f,GetLocation(OBJECT_SELF),TRUE, OBJECT_TYPE_CREATURE);
}
}

View File

@@ -10,4 +10,15 @@ void main()
{
ExecuteScript("prc_rest", OBJECT_SELF);
ExecuteScript("x2_mod_def_rest", OBJECT_SELF);
// Find the nearest summoned Efreeti with the specified tag
object oSummonedEfreeti = GetNearestObjectByTag("SUM_EFREETI001");
// Check if the summoned Efreeti exists and is valid
if (GetIsObjectValid(oSummonedEfreeti))
{
// Destroy the summoned Efreeti immediately
DestroyObject(oSummonedEfreeti, 0.0f);
}
}

75
_module/nss/hputest.nss Normal file
View File

@@ -0,0 +1,75 @@
#include "69_inc_henai"
void main()
{
object oMaster = GetMaster();
ClearAllActions();
SetAssociateState(NW_ASC_IS_BUSY);
int bFound = FALSE;
string sName;
location lCenter = GetLocation(OBJECT_SELF);
object oThing = GetFirstObjectInShape(SHAPE_SPHERE, 15.0, lCenter, TRUE, OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_ITEM);
// Create a list of party members
object oPartyMember = GetFirstFactionMember(oMaster);
while (GetIsObjectValid(oThing))
{
if (GetObjectType(oThing) == OBJECT_TYPE_ITEM)
{
bFound = TRUE;
sName = GetName(oThing);
TurnToFaceObject(oThing);
ActionPickUpItem(oThing);
// Loop through all party members and send a message to each
while (GetIsObjectValid(oPartyMember))
{
if (GetIsPC(oPartyMember))
{
ActionDoCommand(SendMessageToPC(oPartyMember, GetName(OBJECT_SELF) + " picked up " + sName + "."));
}
oPartyMember = GetNextFactionMember(oMaster);
}
}
else // oThing is a placeable
{
if (GetHasInventory(oThing)) // Containers (including corpses)
{
// Don't search locked containers
// Only search trapped containers if you can't see the trap
if (!GetLocked(oThing) && (!GetIsTrapped(oThing) || (GetIsTrapped(oThing) && !GetTrapDetectedBy(oThing, OBJECT_SELF))))
{
bFound = TRUE;
ActionMoveToObject(oThing);
ActionDoCommand(AssignCommand(oThing, PlayAnimation(ANIMATION_PLACEABLE_OPEN)));
TurnToFaceObject(oThing);
ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0, 3.0);
object oItem = GetFirstItemInInventory(oThing);
while (GetIsObjectValid(oItem))
{
ActionDoCommand(SendMessageToPC(oMaster, GetName(OBJECT_SELF) + " picked up " + GetName(oItem) + " from " + GetName(oThing) + "."));
// Loop through all party members and send a message to each
while (GetIsObjectValid(oPartyMember))
{
if (GetIsPC(oPartyMember))
{
ActionDoCommand(SendMessageToPC(oPartyMember, GetName(OBJECT_SELF) + " picked up " + GetName(oItem) + " from " + GetName(oThing) + "."));
}
oPartyMember = GetNextFactionMember(oMaster);
}
ActionTakeItem(oItem, oThing);
oItem = GetNextItemInInventory(oThing);
}
ActionDoCommand(AssignCommand(oThing, PlayAnimation(ANIMATION_PLACEABLE_CLOSE)));
}
}
} // else
oThing = GetNextObjectInShape(SHAPE_SPHERE, 15.0, lCenter, TRUE, OBJECT_TYPE_PLACEABLE | OBJECT_TYPE_ITEM);
} // while(GetIsObjectValid(oThing))
ActionDoCommand(SetAssociateState(NW_ASC_IS_BUSY, FALSE));
if (!bFound)
SpeakString("I don't see where I can find any around here.");
}

View File

@@ -0,0 +1,23 @@
#include "prc_inc_nwscript"
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = PRCGetCreatureSize(oPC);
// Check if the size is medium or larger
if (nSize == CREATURE_SIZE_MEDIUM || nSize == CREATURE_SIZE_LARGE ||
nSize == CREATURE_SIZE_HUGE || nSize == 22 || nSize == 23)
{
// Check if the PC has either "itm_hemp_rope001" or "itm_silk_rope001"
if (GetItemPossessedBy(oPC, "ITM_HEMP_ROPE001") == OBJECT_INVALID ||
GetItemPossessedBy(oPC, "ITM_SILK_ROPE001") == OBJECT_INVALID)
{
return TRUE;
}
}
return FALSE;
}

View File

@@ -0,0 +1,353 @@
// Tag-based script template.
// This is intended to be a starting point for writing an item's tag-based script.
// Copy this to a script whose name is the tag of the item in question.
// Edit the event handlers (scroll down to find them) as desired.
#include "nw_i0_generic"
#include "x2_inc_switches"
// -----------------------------------------------------------------------------
// This first part is standard and generic.
// There should be no need to edit it; just skip down to the next part.
// -----------------------------------------------------------------------------
int RA_DEBUG = 0;
// The individual event handlers.
void OnAcquire(object oEventItem, object oAcquiredBy, object oTakenFrom, int nStackSize);
void OnActivate(object oEventItem, object oActTarget, location lActTarget, object oActivator);
void OnEquip(object oEventItem, object oEquippedBy);
void OnHit(object oEventItem, object oHitTarget, object oCaster);
int OnSpellCast(object oEventItem, int nSpell, object oCaster);
void OnUnacquire(object oEventItem, object oLostBy);
void OnUnequip(object oEventItem, object oUnequippedBy);
// The main function.
void main()
{
int nEvent = GetUserDefinedItemEventNumber();
// Spells might continue to their spell scripts. All other events are
// completely handled by this script.
if ( nEvent != X2_ITEM_EVENT_SPELLCAST_AT )
SetExecutedScriptReturnValue();
// Determine which event triggered this script's execution.
switch ( nEvent )
{
// Item was acquired.
case X2_ITEM_EVENT_ACQUIRE:
OnAcquire(GetModuleItemAcquired(), GetModuleItemAcquiredBy(),
GetModuleItemAcquiredFrom(), GetModuleItemAcquiredStackSize());
break;
// Item was activated ("activate item" or "unique power").
case X2_ITEM_EVENT_ACTIVATE:
OnActivate(GetItemActivated(), GetItemActivatedTarget(),
GetItemActivatedTargetLocation(), GetItemActivator());
break;
// Item was equipped by a PC.
case X2_ITEM_EVENT_EQUIP:
OnEquip(GetPCItemLastEquipped(), GetPCItemLastEquippedBy());
break;
// Item is a weapon that just hit a target, or it is the armor of someone
// who was just hit.
case X2_ITEM_EVENT_ONHITCAST:
OnHit(GetSpellCastItem(), GetSpellTargetObject(), OBJECT_SELF);
break;
// A PC (or certain NPCs) cast a spell at the item.
case X2_ITEM_EVENT_SPELLCAST_AT:
if ( OnSpellCast(GetSpellTargetObject(), GetSpellId(), OBJECT_SELF) )
SetExecutedScriptReturnValue();
break;
// Item was unacquired.
case X2_ITEM_EVENT_UNACQUIRE:
OnUnacquire(GetModuleItemLost(), GetModuleItemLostBy());
break;
// Item was unequipped by a PC.
case X2_ITEM_EVENT_UNEQUIP:
OnUnequip(GetPCItemLastUnequipped(), GetPCItemLastUnequippedBy());
break;
}
}
// -----------------------------------------------------------------------------
// Event handlers
// -----------------------------------------------------------------------------
// This second part is where you add your desired functionality. Each event
// has its own function with relavant information passed as parameters.
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// oEventItem was acquired (by a PC or an NPC).
// Run by the module.
void OnAcquire(object oEventItem, object oAcquiredBy, object oTakenFrom, int nStackSize)
{
// Default: do nothing.
}
// -----------------------------------------------------------------------------
// oEventItem was activated ("activate item" or "unique power").
// Run by the module.
void OnActivate(object oEventItem, object oActTarget, location lActTarget, object oActivator)
{
//:: Declare major variables
object oPC = oActTarget;
object oItem = GetItemActivated();
object oSpawn;
effect eEffect;
effect eVFX;
int nRandom = d100(1);
if (RA_DEBUG)
{
SendMessageToPC(oPC, "Efreeti Bottle Tag Based Script is running");
SendMessageToPC(oPC, "Rolled a "+ IntToString(nRandom) +".");
}
//:: Have the item activator check if the player has already summoned an efreeti.
object oExistingEfreeti = GetNearestObjectByTag("SUM_EFREETI001");
eEffect = GetFirstEffect(oPC);
while(GetIsEffectValid(eEffect))
{
if(GetEffectTag(eEffect) == GetName(oPC)+"SummonedEfreeti")
RemoveEffect(oPC, eEffect);
eEffect = GetNextEffect(oPC);
}
if (GetIsObjectValid(oExistingEfreeti))
{
SendMessageToPC(oPC, "You can only summon one Efreeti per day.");
return;
}
//:: If success on a 10% chance.
if ( nRandom <= 10 )
{
//:: Spawn Hostile Efreeti.
eVFX = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_FIRE);
oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "sum_efreeti001", GetLocation(oActivator));
AssignCommand(oSpawn, DetermineCombatRound(oPC));
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oSpawn));
// Set the player's "SummonedEfreeti" variable to 1 to mark that an efreeti has been summoned.
SetLocalInt(oPC, GetName(oPC)+"SummonedEfreeti", 1);
SendMessageToPC(oPC, "The efreeti is insane and attacks immediately!");
//:: Create the non-magical bottle
object oDeadBottle = CreateItemOnObject("ITM_DEADBOTTLE", oPC, 1);
//:: Destroy the original magical bottle
DestroyObject(oItem);
}
//:: Else if, the next 20%.
/* else if ( nRandom < 21 && nRandom > 10 )
{
Remarked out until I get the Wish spell figured out.
//:: Spawn Friendly Efreeti.
eVFX = EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_FIRE);
oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "sum_efreeti001", GetLocation(oActivator));
AssignCommand(oSpawn, ActionStartConversation(oPC));
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oSpawn));
SetIsTemporaryFriend(oPC, oSpawn, FALSE);
SendMessageToPC(oPC, "The efreeti is friendly & wants to speak!");
// Set the player's "SummonedEfreeti" variable to 1 to mark that an efreeti has been summoned.
SetLocalInt(oPC, GetName(oPC)+"SummonedEfreeti", 1);
//:: Create the non-magical bottle
object oDeadBottle = CreateItemOnObject("ITM_DEADBOTTLE", oPC, 1);
//:: Destroy the original magical bottle
DestroyObject(oItem);
} */
//:: Else, the remainder.
else
{
//:: Have the item activator check if the player has already summoned an efreeti.
object oExistingEfreeti = GetObjectByTag(GetName(oPC)+"SummonedEfreeti");
int nSummoned = GetLocalInt(oPC, GetName(oPC)+"SummonedEfreeti");
if (!GetIsObjectValid(oExistingEfreeti) && nSummoned == 0)
{
// No Efreeti exists and the player hasn't summoned one yet, so we can summon a new one.
eEffect = EffectSummonCreature("efreeti001", VFX_FNF_GAS_EXPLOSION_FIRE, 1.0);
eEffect = MagicalEffect(eEffect);
eEffect = TagEffect(eEffect, GetName(oPC)+"SummonedEfreeti");
DelayCommand(0.5f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oActivator, 600.0f));
DelayCommand(600.0f, DeleteLocalInt(oPC, GetName(oPC)+"SummonedEfreeti"));
SendMessageToPC(oPC, "The efreeti grudgingly serves you for a time.");
// Set the player's "SummonedEfreeti" variable to 1 to mark that an efreeti has been summoned.
SetLocalInt(oPC, GetName(oPC)+"SummonedEfreeti", 1);
}
else
{
// An Efreeti is already present or has been summoned by the player; inform the player.
SendMessageToPC(oPC, "You can only summon one Efreeti per day.");
}
}
}
// -----------------------------------------------------------------------------
// oEventItem was equipped by a PC.
// Run by the module.
void OnEquip(object oEventItem, object oEquippedBy)
{
// Default: do nothing.
}
// -----------------------------------------------------------------------------
// oEventItem is a weapon that just hit a target, or it is the armor of someone who
// was just hit by someone else's weapon.
// Run by the caster.
void OnHit(object oEventItem, object oHitTarget, object oCaster)
{
// Default: do nothing.
}
// -----------------------------------------------------------------------------
// Someone cast a spell at oEventItem.
// This usually only fires if a PC cast the spell, but it also fires for
// DM-possessed NPCs and NPCs in an area with the "X2_L_WILD_MAGIC" local integer set.
//
// Return TRUE to prevent the spell script from firing.
// Return FALSE to proceed normally.
//
// This fires after the UMD check, module spellhook, item creation, and
// sequencer handlers decide they do not want to handle/interrupt this spell.
// This fires before the check to see if this is a spell that normally can
// target items (and before the spell script itself runs).
//
// Run by the caster.
int OnSpellCast(object oEventItem, int nSpell, object oCaster)
{
// Default: just proceed normally.
return FALSE;
}
// -----------------------------------------------------------------------------
// oEventItem was unacquired/lost (by a PC or NPC).
// Run by the module.
void OnUnacquire(object oEventItem, object oLostBy)
{
// Default: do nothing.
}
// -----------------------------------------------------------------------------
// oEventItem was unequipped by a PC.
// Run by the module.
void OnUnequip(object oEventItem, object oUnequippedBy)
{
// Default: do nothing.
}
//:: void main (){}
/* // Declare constants for the chances of the efreeti's behavior
const int CHANCE_INSANE = 10;
const int CHANCE_GRANT_WISHES = 10;
// Declare constants for the efreeti's actions
const int ACTION_INSANE = 1;
const int ACTION_GRANT_WISHES = 2;
const int ACTION_SERVE_CHARACTER = 3;
#include "nw_i0_generic"
void main()
{
//:: Declare major variables
object oPC = GetItemActivator();
object oItem = GetItemActivated();
object oSpawn;
effect eVFX;
//:: Roll a d% to determine the efreeti's behavior
int nRoll = d100(1);
//:: Determine the efreeti's action based on the roll
int nEfreetiAction;
if (nRoll <= CHANCE_INSANE)
{
nEfreetiAction = ACTION_INSANE;
}
else if (nRoll <= CHANCE_INSANE + CHANCE_GRANT_WISHES)
{
nEfreetiAction = ACTION_GRANT_WISHES;
}
else
{
nEfreetiAction = ACTION_SERVE_CHARACTER;
}
//:: Handle the efreeti's action
switch (nEfreetiAction)
{
case ACTION_INSANE:
SendMessageToPC(oPC, "The efreeti is insane and attacks immediately!");
//:: Spawn hostile Efreeti.
eVFX = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3);
oSpawn = CreateObject(OBJECT_TYPE_CREATURE, "efreeti001", GetLocation(oPC));
AssignCommand(oSpawn, DetermineCombatRound(oPC));
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVFX, oSpawn));
break;
case ACTION_GRANT_WISHES:
SendMessageToPC(oPC, "The efreeti is friendly & wants to speak!");
//:: Spawn friendly Efreeti.
// Insert code here to handle the granting of wishes
break;
case ACTION_SERVE_CHARACTER:
SendMessageToPC(oPC, "The efreeti loyally serves you for a time.");
effect eSummon = EffectSummonCreature("efreeti001", VFX_NONE);
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, GetLocation(oPC), TurnsToSeconds(10));
/* //:: Summon Efreeti.
effect eSummon = EffectSummonCreature("efreeti001", VFX_FNF_SUMMON_MONSTER_3);
DelayCommand(0.5f, ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, GetLocation(oPC), TurnsToSeconds(10)));
break;
}
/* // If the efreeti is insane or grants wishes, swap out the bottle with "ITM_DEADBOTTLE"
if (nEfreetiAction == ACTION_INSANE || nEfreetiAction == ACTION_GRANT_WISHES)
{
// Create the non-magical bottle
object oDeadBottle = CreateObject(OBJECT_TYPE_ITEM, "ITM_DEADBOTTLE", GetLocation(oItem));
// Destroy the original magical bottle
DestroyObject(oItem);
}
} */

View File

@@ -0,0 +1,36 @@
// Custom script for the OnUsed event of a placable
// Simulates climbing a rope up 20 feet
#include "prc_misc_const"
void main()
{
object oPC = GetLastUsedBy();
int nClimbSkill = GetSkillRank(SKILL_CLIMB, oPC);
int nClimbDC = 5;
location locDestination1 = GetLocation(GetWaypointByTag("WP_LATRENE_EXIT"));
location locDestination2 = GetLocation(GetWaypointByTag("WP_LATRENE3"));
// Roll a d20 for the Climb check
int nRoll = d20();
// Add the Climb skill rank to the roll
nRoll += nClimbSkill;
// Check if the roll meets or exceeds the DC
if (nRoll >= nClimbDC)
{
// Successful climb, move the player to the destination
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionJumpToLocation(locDestination1));
}
else
{
// Failed climb, apply 2d6 bludgeoning damage and move the player back to WP_LATRENE3
int nDamage = d6(2); // Roll 2d6 for damage
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING), oPC);
AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionJumpToLocation(locDestination2));
AssignCommand(oPC, SpeakString("Ow!"));
}
}

View File

@@ -0,0 +1,36 @@
void main()
{
// Declare major variables
object oPlaceable = OBJECT_SELF;
// Check if the Dung Monster has already been spawned in the module
int DungMonsterSpawned = GetLocalInt(GetModule(), "DungMonsterSpawned");
// If it's not already spawned, spawn the Dung Monster
if (DungMonsterSpawned == 0)
{
// Spawn the Dung Monster
object oCreature = CreateObject(OBJECT_TYPE_CREATURE, "ra_dungmonster01", GetLocation(oPlaceable));
// Get the nearest player to the placeable
object oNearestPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, oPlaceable);
// If we found a player, make the creature attack them
if (GetIsObjectValid(oCreature) && GetIsObjectValid(oNearestPlayer))
{
AssignCommand(oCreature, ActionAttack(oNearestPlayer));
}
// Set the Dung Monster as spawned in the module
SetLocalInt(GetModule(), "DungMonsterSpawned", 1);
}
// Clear the plot flag on the commode
SetPlotFlag(oPlaceable, FALSE);
// Destroy the commode
DestroyObject(oPlaceable, 0.0f);
// Spawn the latrine hole
object oHole = CreateObject(OBJECT_TYPE_PLACEABLE, "ra_plc_dm_hole", GetLocation(oPlaceable));
}

View File

@@ -0,0 +1,89 @@
//::////////////////////////////////////////////////////////////////////////////
/*//
Level 1a: Latrene 3
onEnter script
ra_lvl01a_onentr.nss
Wandering Monsters: None
Detections: Faint evil from the whole place; slightly more to the south east.
Continuous Effects: The stench of this level requires all characters to make
a Fortitude save (DC 10) upon entering the level and every 30 minutes
thereafter or all rolls are at 2 morale penalty due to the distraction
caused by the overpowering smell.
*///
//::////////////////////////////////////////////////////////////////////////////
#include "spawn_functions"
#include "tgdc_explore_inc"
void StenchMessage(object oPC = OBJECT_SELF)
{
//:: Only fire for (real) PCs.
if ( !GetIsPC(oPC) || GetIsDMPossessed(oPC) )
return;
//:: Have text appear over the PC's head.
FloatingTextStringOnCreature("The smell of this cesspool is making you physically ill.", oPC, FALSE);
}
void main()
{
//:: Get the entering object (usually a PC)
object oPC = GetEnteringObject();
//:: Only fire once per PC.
if (!GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
{
StenchMessage(oPC);
SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
}
/*
Spawn_OnAreaEnter() can take three arguments - the name of the heartbeat
script to execute, the heartbeat duration, and a delay for the first
heartbeat. They default to spawn_sample_hb, 6.0, and 0.0 respectively; as
if it were called like: Spawn_OnAreaEnter( "spawn_sample_hb", 6.0, 0.0 );
*/
if ( GetIsAreaAboveGround( OBJECT_SELF ) && ! GetIsAreaNatural( OBJECT_SELF ) )
{
//:: Indoors - no delay on the first HB
Spawn_OnAreaEnter( "spawn_sample_hb", 6.0, 0.0 );
}
else
{
//:: Outdoors or underground - do a 3 second delay on the first HB
Spawn_OnAreaEnter( "spawn_sample_hb", 6.0, 3.0 );
}
//:: Records that the PC has entered Rappan Athuk at least once.
SetLocalInt(oPC, "bEnteredDungeon", 1);
SetLocalInt(oPC, "bEnteredLevelOne", 1);
}

View File

@@ -0,0 +1,50 @@
//::////////////////////////////////////////////////////////////////////////////
/*//
Level 1a: Latrene 3
onExit script
ra_lvl01a_onexit.nss
Wandering Monsters: None
Detections: Faint evil from the whole place; slightly more to the south east.
Continuous Effects: The stench of this level requires all characters to make
a Fortitude save (DC 26) upon entering the level and every 2 minutes
thereafter become Nauseated due to the overpowering smell.
*///
//::////////////////////////////////////////////////////////////////////////////
void main()
{
//:: Get the entering object (usually a PC)
object oPC = GetExitingObject();
//:: Clears Level 1a stench message int var,
//:: so it will show up again next time they enter
DelayCommand(0.0f,DeleteLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)));
}

View File

@@ -0,0 +1,107 @@
//::////////////////////////////////////////////////////////////////////////////
/*//
Level 1a: Latrene 3
onHeartbeat script
ra_lvl01a_onhb.nss
Wandering Monsters: None
Detections: Faint evil from the whole place; slightly more to the south east.
Continuous Effects: The stench of this level requires all characters to make
a Fortitude save (DC 26) upon entering the level and every 2 minutes
thereafter become Nauseated due to the overpowering smell.
*///
//::////////////////////////////////////////////////////////////////////////////
#include "prc_inc_spells"
//:: Function to process the stench penalty
void ApplySick(object oPC)
{
int RA_DEBUG = 0;
//:: Check for exising variable on player
int oldTime = GetLocalInt(oPC, "StenchFortSaveTime");
// Get the current system time in seconds
int newTime = (GetTimeHour()*60*60)+(GetTimeMinute()*60)+GetTimeSecond();
// Calculate the time difference in seconds
int timeDifference = newTime - oldTime;
if (RA_DEBUG)
{
SendMessageToPC(oPC, "oldTime = " + IntToString(oldTime));
SendMessageToPC(oPC, "newTime = " + IntToString(newTime));
SendMessageToPC(oPC, "timeDifference = " + IntToString(timeDifference));
}
//:: Check if the character hasn't made a Fortitude save in the last 3 minutes
if (oldTime == 0 || timeDifference >= 15)
{
//:: Check if the character failed the save
if (!FortitudeSave(oPC, 26))
{
//:: Apply Nausea
effect eNauseated = EffectNausea(oPC, 12.0f);
effect eVFX = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
effect eLink = EffectLinkEffects(eNauseated, eVFX);
eLink = SupernaturalEffect(eLink);
eLink = TagEffect(eLink, "LatreneStench");
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, 12.0f); // 12 seconds = 2 in-game minutes.
//:: Store the current time on player
SetLocalInt(oPC, "LatreneFortSaveTime", newTime);
if (RA_DEBUG)
{
SendMessageToPC(oPC, "Failed LatreneFortSave");
SendMessageToPC(oPC, "Setting LatreneFortSaveTime as " + IntToString(newTime));
}
// Send a message to the player
SendMessageToPC(oPC, "The overpowering stench is nauseating you.");
}
//:: Store the current time on player
SetLocalInt(oPC, "LatreneFortSaveTime", newTime);
if (RA_DEBUG)
{
SendMessageToPC(oPC, "Passed LatreneFortSave");
SendMessageToPC(oPC, "Setting LatreneFortSaveTime as " + IntToString(newTime));
}
}
}
void main()
{
int RA_DEBUG = 0;
//:: Declare major variables
object oArea = OBJECT_SELF;
object oPC = GetFirstObjectInArea(oArea, OBJECT_TYPE_CREATURE);
while (GetIsObjectValid(oPC))
{
if (GetIsPC(oPC) || (GetMaster(oPC) != OBJECT_INVALID && GetIsPC(GetMaster(oPC))))
{
if (RA_DEBUG)
{
SendMessageToPC(oPC, "Running Level 1a Area HB");
}
//:: Apply the stench
ApplySick(oPC);
}
// Get the next object in the area
oPC = GetNextObjectInArea(oArea);
}
}

View File

@@ -0,0 +1,16 @@
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = GetCreatureSize(oPC);
// Check if the size is small, tiny, diminutive, or fine
if (nSize == CREATURE_SIZE_SMALL || nSize == CREATURE_SIZE_TINY ||
nSize == 20 || nSize == 21)
{
return TRUE;
}
return FALSE;
}

View File

@@ -0,0 +1,23 @@
#include "prc_inc_nwscript"
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = PRCGetCreatureSize(oPC);
// Check if the size is medium or larger
if (nSize == CREATURE_SIZE_MEDIUM || nSize == CREATURE_SIZE_LARGE ||
nSize == CREATURE_SIZE_HUGE || nSize == 22 || nSize == 23)
{
// Check if the PC has either "itm_hemp_rope001" or "itm_silk_rope001"
if (GetItemPossessedBy(oPC, "ITM_HEMP_ROPE001") != OBJECT_INVALID ||
GetItemPossessedBy(oPC, "ITM_SILK_ROPE001") != OBJECT_INVALID)
{
return TRUE;
}
}
return FALSE;
}

View File

@@ -0,0 +1,16 @@
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = GetCreatureSize(oPC);
// Check if the size is small, tiny, diminutive, or fine
if (nSize == CREATURE_SIZE_SMALL || nSize == CREATURE_SIZE_TINY ||
nSize == 20 || nSize == 21)
{
return FALSE;
}
return TRUE;
}

View File

@@ -0,0 +1,23 @@
#include "prc_inc_nwscript"
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = PRCGetCreatureSize(oPC);
// Check if the size is small, tiny, diminutive, or fine
if (nSize == CREATURE_SIZE_SMALL || nSize == CREATURE_SIZE_TINY ||
nSize == 20 || nSize == 21)
{
// Check if the PC has either "itm_hemp_rope001" or "itm_silk_rope001"
if (GetItemPossessedBy(oPC, "ITM_HEMP_ROPE001") != OBJECT_INVALID ||
GetItemPossessedBy(oPC, "ITM_SILK_ROPE001") != OBJECT_INVALID)
{
return TRUE;
}
}
return FALSE;
}

View File

@@ -0,0 +1,23 @@
#include "prc_inc_nwscript"
int StartingConditional()
{
object oPC = GetPCSpeaker();
// Check if the PC's size is small, tiny, diminutive, or fine
int nSize = PRCGetCreatureSize(oPC);
// Check if the size is small, tiny, diminutive, or fine
if (nSize == CREATURE_SIZE_SMALL || nSize == CREATURE_SIZE_TINY ||
nSize == 21 || nSize == 22)
{
// Check if the PC has either "itm_hemp_rope001" or "itm_silk_rope001"
if (GetItemPossessedBy(oPC, "ITM_HEMP_ROPE001") == OBJECT_INVALID ||
GetItemPossessedBy(oPC, "ITM_SILK_ROPE001") == OBJECT_INVALID)
{
return TRUE;
}
}
return FALSE;
}

View File

@@ -8300,7 +8300,7 @@ at night. */
//:: Dungeon Level 1 Random Encounters
if (sCamp == "enc_level01")
{
int nSpawn = Random(20) + 1;
int nSpawn = d20(1);
switch(nSpawn)
{
case 1:
@@ -8599,7 +8599,7 @@ at night. */
//:: 1 Gelatinous Cube: 04 HD
case 4:
//:: 1 Dung Monster: 10 HD
//:: 1 Dung Monster: 10 HD or 1d2 Shadows: 03 HD
{
// Set Number of Placeables
SetLocalInt(oCamp, "CampNumP", 0);
@@ -8625,14 +8625,31 @@ at night. */
// Set Placeable 1 and Spawn Flags
//SetLocalString(oCamp, "CampP1", "plc_chest1");
//SetLocalString(oCamp, "CampP1_Flags", "SP_PL3T80P30");
string sCreatureTag = "RA_DUNGMONSTER01"; // Replace with the desired tag.
object oCreature = GetObjectByTag(sCreatureTag);
// Set Creature 0 and Spawn Flags
SetLocalString(oCamp, "CampC0", "ra_dungmonster01");
SetLocalString(oCamp, "CampC0_Flags", "SP_RW_CD060");
if (GetIsObjectValid(oCreature))
{
// The creature with the specified tag exists in the module.
// You can add your code here to handle this case.
break;
}
//:: 1 Dung Monster: 10 HD
// Set Number of Creatures
SetLocalInt(oCamp, "CampNumC", d2(1));
// Set Creature 0 and Spawn Flags
SetLocalString(oCamp, "CampC0", "shadow001");
SetLocalString(oCamp, "CampC0_Flags", "SP_RW_CD060");
}
else
{
// Set Creature 0 and Spawn Flags
SetLocalString(oCamp, "CampC0", "ra_dungmonster01");
SetLocalString(oCamp, "CampC0_Flags", "SP_RW_CD060");
DelayCommand(0.0f, SetLocalInt(GetModule(), "DungMonsterActive", TRUE));
}
}
//:: 1 Dung Monster: 10 HD or 1d2 Shadows: 03 HD
case 5: case 6: case 7: case 8: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20:
//:: 1 Dire Rat
@@ -8669,10 +8686,10 @@ at night. */
break;
}
//:: 1 Dire Rat
}
}
}
//:: Dungeon Level 1 Random Encounters
//:: Dungeon Level 1 Random Encounters
//:: The Dishonest Patrol (EL 11)
if (sCamp == "dishonest_patrol")

View File

@@ -151,6 +151,38 @@ int SpawnCheckCustom(object oSpawn)
//:: they have been inside the dungeon & Sheriff Ostland is still alive.
//:: Process spawn if Dung Monster *is not* roaming & *not* "dead" (Commode)
if (nSpawnCheckCustom == 11)
{
int iDungMonActive = GetLocalInt(GetModule(), "DungMonsterActive");
int iDungMonDead = GetLocalInt(GetModule(), "DungMonsterDead");
if (iDungMonActive && iDungMonDead)
{
nProcessSpawn = FALSE;
}
}
//:: Process spawn if Dung Monster *is not* roaming & *not* "dead" (Commode)
//:: Process spawn if Dung Monster *is* roaming or is "dead" (Hole)
if (nSpawnCheckCustom == 12)
{
int iDungMonActive = GetLocalInt(GetModule(), "DungMonsterActive");
int iDungMonDead = GetLocalInt(GetModule(), "DungMonsterDead");
if (iDungMonActive || iDungMonDead)
{
nProcessSpawn = TRUE;
}
}
//:: Process spawn if Dung Monster *is* roaming or is "dead" (Hole)
//:: Checks for stage 1 or lower for the "Spider's Captive quest"
if (nSpawnCheckCustom == 50)
{
@@ -199,8 +231,8 @@ int SpawnCheckCustom(object oSpawn)
//:: Checks for stage 2 or lower for the "Spider's Captive quest"
/* //:: Checks for stage 98 or lower (Drusilla's not dead) for the "Vengeful Druid quest"
if (nSpawnCheckCustom == 52)
/* //:: Checks for stage 98 or lower (Drusilla's not dead) for the "Vengeful Druid quest" //:: I wish past me left a note
if (nSpawnCheckCustom == 52) //:: for future me on why this was disabled
{
//:: Initialize major variables
object oArea = GetArea(OBJECT_SELF);
@@ -246,6 +278,9 @@ int SpawnCheckCustom(object oSpawn)
//:: Checks for non-completion of "The Outcasts" quest
// -------------------------------------------
// Only Make Modifications Between These Lines
//

View File

@@ -2,7 +2,7 @@
// Spawn Check - PCs
//
// void main (){}
//:: void main (){}
#include "pqj_inc"
@@ -49,16 +49,16 @@ int SpawnCheckPCs(object oSpawn)
// Only Make Modifications Between These Lines
// -------------------------------------------
// Check 00
//:: Example Check 00
if (nCheckPCs == 0)
{
// Example, Allow Spawn
nProcessSpawn = TRUE;
}
//
//:: Example Check 00
// Spawn with a Skill Check
//:: Spawn with a Skill Check
if (nCheckPCs == 1)
{
// Get Current Number of Children
@@ -84,7 +84,8 @@ int SpawnCheckPCs(object oSpawn)
}
}
}
//
//:: Spawn with a Skill Check
//:: Spawn with a 25DC Skill Check
if (nCheckPCs == 2)
@@ -112,9 +113,10 @@ int SpawnCheckPCs(object oSpawn)
}
}
}
//:: Spawn with a 25DC Skill Check
//:: Spawn with a 25DC Skill Check
// Spawn Based on Journal Quest Entry
//:: Spawn Based on Journal Quest Entry
if (nCheckPCs == 3)
{
// Check Journal Quest Entry
@@ -125,9 +127,10 @@ int SpawnCheckPCs(object oSpawn)
nProcessSpawn = TRUE;
}
}
//
//:: Spawn Based on Journal Quest Entry
// Spawn Based on Item in PC Inventory
// Spawn Based on Item in PC Inventory
if (nCheckPCs == 4)
{
// Check Player for Item
@@ -142,7 +145,8 @@ int SpawnCheckPCs(object oSpawn)
oItem = GetNextItemInInventory(oPC);
}
}
//
// Spawn Based on Item in PC Inventory
//:: Checks for non-completion of "The Outcasts" quest.
if (nCheckPCs == 5)
@@ -158,7 +162,7 @@ int SpawnCheckPCs(object oSpawn)
//:: Checks for non-completion of "The Outcasts" quest.
//:: #52 - Spawn if Drusilla isn't dead
//:: #52 - Spawn if Drusilla isn't dead
if (nCheckPCs == 52)
{
// Check Journal Quest Entry
@@ -169,7 +173,20 @@ int SpawnCheckPCs(object oSpawn)
nProcessSpawn = TRUE;
}
}
//:: #52 - Spawn if Drusilla isn't dead
//:: #52 - Spawn if Drusilla isn't dead
//:: #99 Checks to see if a nearby PC is using Detect Magic.
if (nCheckPCs == 99)
{
// Check if player is using Detect Magic (spellID 1576)
if (GetHasSpellEffect(1576, oPC))
{
nProcessSpawn = TRUE;
}
}
//:: #99 Checks to see if a nearby PC is using Detect Magic.
// -------------------------------------------
// Only Make Modifications Between These Lines

View File

@@ -2,7 +2,7 @@
//:: Name x2_def_ondeath
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
/*
Default OnDeath script
*/
//:://////////////////////////////////////////////
@@ -12,7 +12,19 @@
void main()
{
object oNPC = OBJECT_SELF;
object oNPC = OBJECT_SELF;
string sResRef = GetResRef(oNPC);
//:: Special handling for Dung Monster
if (sResRef == "ra_dungmonster")
{
float fRejuveTime = HoursToSeconds(24) * d4(1);
SetLocalInt(GetModule(), "DungMonsterActive", FALSE);
SetLocalInt(GetModule(), "DungMonsterDead", TRUE);
ActionDoCommand(DelayCommand(fRejuveTime, SetLocalInt(GetModule(), "DungMonsterDead", FALSE)));
}
// Makes sure armor's droppable flag is set to 0
SetDroppableFlag(GetItemInSlot(INVENTORY_SLOT_CHEST, OBJECT_SELF), 0);

View File

@@ -466,7 +466,7 @@ void main()
//:: Dung Monster texture override
if (sResRef == "ra_dungmonster01")
{
ReplaceObjectTexture(OBJECT_SELF,"yochlol_eye", "black");
ReplaceObjectTexture(OBJECT_SELF,"yochlol_eye", "poop01");
ReplaceObjectTexture(OBJECT_SELF,"yochlol_skin", "poop01");
}