Bugfix pass.

Fixed onRespawn & onDying scripts.  Fixed XP awards.  Added temple hospital & library.
This commit is contained in:
Jaysyn904
2021-09-25 20:28:28 -04:00
parent 6195a6cf23
commit 3e3128ed1e
84 changed files with 64542 additions and 169 deletions

View File

@@ -0,0 +1,12 @@
// Starts the Good Temple Store.
#include "nw_i0_plot"
void main()
{
object oStore = GetNearestObjectByTag("GoodTempleStore");
if(GetObjectType(oStore) == OBJECT_TYPE_STORE)
gplotAppraiseOpenStore(oStore, GetPCSpeaker());
else
ActionSpeakStringByStrRef(53090, TALKVOLUME_TALK);
}

View File

@@ -0,0 +1,23 @@
/*
Conversation: persuade check with difficulty class of 25
(Pretty Damn Tricky). However, if PC is very low on hit points,
the difficulty drops to 12 (Rather Simple).
By WWWWolf 2003-10-29
*/
int StartingConditional()
{
object pc = GetPCSpeaker();
float hpratio = ( IntToFloat(GetCurrentHitPoints(pc)) /
IntToFloat(GetMaxHitPoints(pc)) );
int dc = 25; // Normal difficulty class
if(hpratio < 0.15f)
dc = 12; // Low-HP difficulty class
if(GetIsSkillSuccessful(pc, SKILL_PERSUADE, dc))
return TRUE;
return FALSE;
}

View File

@@ -149,6 +149,9 @@ void main()
}
// Signal the death event.
FireUserEvent(AI_FLAG_UDE_DEATH_EVENT, EVENT_DEATH_EVENT);
ExecuteScript("prc_npc_death", OBJECT_SELF);
ExecuteScript("prc_pwondeath", OBJECT_SELF);
}
// We need a wrapper. If the amount of deaths, got in this, is not equal to iDeaths,

View File

@@ -0,0 +1,17 @@
/**
* Custom PW OnDeath script to be used with the PRC and pwfxp system.
* Created by: fluffyamoeba
* Created on: 2007-11-14
*
* Usage: put in your PW's module.
*
* This script is executed by nw_c2_default7 (the default NPC OnDeath script)
* if using the PRC.
*/
// calls the pwfxp script.
void main ()
{
ExecuteScript("pwfxp", OBJECT_SELF);
}

View File

@@ -9,14 +9,14 @@ changes: 2007-11-14
- pwfxp_prc_race now reads the 2da cache directly.
- the race LA is done entirely through this script. DO NOT set PRC_XP_USE_SIMPLE_LA
- the race LA is done entirely through this script. DO NOT set PRC_XP_USE_SIMPLE_LA
or the XP penalty will be applied twice
- if using this with the supplied prc_pwondeath script, you don't need to make any
changes to nw_c2_default7 (the OnDeath script)
- prc_racial_const no longer used
=================
Include added for prc races: pwfxp_prc_race, modify this file if you want to
@@ -92,7 +92,7 @@ Silvercloud
ExecuteScript("pwfxp",OBJECT_SELF);
Don't forget to set the XP-Scale slider to 0 (module properties)
*note* if using your own prc_pwondeath script add this to that script instead.
ATTENTION: HOW TO REMOVE THE DOUBLE XP MESSAGE !

View File

@@ -21,7 +21,7 @@
//
// you can further scale the leveling progress more precisely with the PWFXP_LEVEL_MODIFIERS constant
// just continue to read my comments...
const float PWFXP_GLOBAL_MODIFIER = 10.0;
const float PWFXP_GLOBAL_MODIFIER = 15.0;
// displays one-line XP status info after each kill
// useful while you fine tune the system.
@@ -239,11 +239,11 @@ const float PWFXP_GROUPBONUS_MODIFIER = 0.1;
// groub members need to be within this distance to the dead creature
// if they want to get any XP during fights
const float PWFXP_MAXIMUM_DISTANCE_TO_GROUP = 30.0; // meters
const float PWFXP_MAXIMUM_DISTANCE_TO_GROUP = 70.0; // meters
// safety mechanism
// minimum XP for a kill
const int PWFXP_MINIMUM_XP = 0;
const int PWFXP_MINIMUM_XP = 1;
// safety mechanism
// maximum XP for a kill

View File

@@ -1,15 +1,14 @@
#include "nw_i0_plot"
/* Script generated by
Lilac Soul's NWN Script Generator, v. 2.1
For download info, please visit:
http://nwvault.ign.com/View.php?view=Other.Detail&id=4683&id=625 */
//Goes OnPlayerRespawn of the module properties
void main()
{
object oPC = GetLastRespawnButtonPresser();
object oTarget;
location lTarget;
oTarget = GetWaypointByTag("townport");
lTarget = GetLocation(oTarget);
if (!GetIsPC(oPC)) return;
@@ -19,11 +18,6 @@ ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oPC)), oPC)
RemoveEffects(oPC);
object oTarget;
location lTarget;
oTarget = GetWaypointByTag("townport");
lTarget = GetLocation(oTarget);
//only do the jump if the location is valid.
//though not flawless, we just check if it is in a valid area.
@@ -35,9 +29,7 @@ if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;
AssignCommand(oPC, ClearAllActions());
DelayCommand(3.0, AssignCommand(oPC, ActionJumpToLocation(lTarget)));
oTarget = oPC;
DelayCommand(0.1, AssignCommand(oPC, ActionJumpToLocation(lTarget)));
//Visual effects can't be applied to waypoints, so if it is a WP
//apply to the WP's location instead
@@ -45,7 +37,7 @@ oTarget = oPC;
int nInt;
nInt = GetObjectType(oTarget);
if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), oTarget);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), GetLocation(oTarget));
if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), oPC);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), GetLocation(oPC));
}

View File

@@ -0,0 +1,16 @@
/*
Operation assistant heartbeat.
WWWWolf 2003-10-09
*/
#include "temple_fun"
void main()
{
NormalHeartbeat();
if(TooBusyToConverse())
return;
FaceToMyLocation();
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_CURE_CRITICAL_WOUNDS, 200);
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_CURE_LIGHT_WOUNDS, 50);
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_CURE_CRITICAL_WOUNDS, 0);
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_CURE_LIGHT_WOUNDS, 0);
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_LESSER_RESTORATION, 0);
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_NEUTRALIZE_POISON, 0);
}

View File

@@ -0,0 +1,45 @@
/*
Temple functions include file.
WWWWolf 2003-11-09
*/
string CASTER = "Marleta";
void CastSpellOnPC(int spell, int cost)
{
object pc = GetPCSpeaker();
object caster = GetObjectByTag(CASTER);
if(cost > 0) {
TakeGoldFromCreature(cost, pc, TRUE);
}
AssignCommand(caster, ActionPauseConversation());
AssignCommand(caster, ActionCastSpellAtObject(spell, pc, METAMAGIC_NONE,
TRUE, 5, TRUE));
AssignCommand(caster, ActionResumeConversation());
}
void NormalHeartbeat()
{
// Run normal heartbeat stuff
ExecuteScript("nw_c2_default1",OBJECT_SELF);
}
int TooBusyToConverse()
{
return(GetIsInCombat() || IsInConversation(OBJECT_SELF));
}
// Create a waypoint called <creaturetag>Location.
// Subject will take the waypoint's location and walk there,
// and face where the waypoint is pointing.
void FaceToMyLocation()
{
object wp = GetObjectByTag(GetTag(OBJECT_SELF)+"Location");
location here = GetLocation(wp);
ActionMoveToLocation(here);
SetFacing(GetFacing(wp)); // Turn to the direction of the waypoint
}

View File

@@ -0,0 +1,6 @@
int StartingConditional()
{
if(GetGold(GetPCSpeaker()) >= 100)
return TRUE;
return FALSE;
}

View File

@@ -0,0 +1,6 @@
int StartingConditional()
{
if(GetGold(GetPCSpeaker()) >= 200)
return TRUE;
return FALSE;
}

View File

@@ -0,0 +1,6 @@
int StartingConditional()
{
if(GetGold(GetPCSpeaker()) >= 50)
return TRUE;
return FALSE;
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_LESSER_RESTORATION, 100);
}

View File

@@ -0,0 +1,104 @@
/*
Make the patients moan. This is a heartbeat script, placed not on
any of the individual patients, but rather, on some innocuous
placeable object (rug, scorchmark, blood puddle, etc...)
No need to make millions of heartbeat scripts =)
WWWWolf 2003-11-09
*/
// Patient tag.
const string PATIENT = "Patient";
// NOTE: BROKEN (below code uses a brute-force approach.)
// Causes "TOO MANY INSTRUCTIONS" error.
int HowManyWithTag(string sTag) {
object obj;
int n = 0;
do {
obj = GetObjectByTag(sTag,n);
} while (obj != OBJECT_INVALID);
return n;
}
object RandomPatient() {
object x;
/* // Optimal solution
x = GetObjectByTag(PATIENT, Random(n));
if(x == OBJECT_INVALID)
continue;
*/
/* // Brute force but safe solution
int z;
for(z = 0; z < 10; z++) { // 10 tries
x = GetObjectByTag(PATIENT,Random(40));
if(x != OBJECT_INVALID)
break;
}
if(x == OBJECT_INVALID)
continue;
*/
// Lightweight brute force solution
x = GetObjectByTag(PATIENT,Random(40));
/* if(x == OBJECT_INVALID)
continue; */
return x;
}
string RandomMoaning() {
// Pick a random moaning
switch(d6(1)) {
default:
case 1:
return "Aaaaargh!";
break;
case 2:
return "Oooooh my head!";
break;
case 3:
return "Aaaaargh my legs!";
break;
case 4:
return "Uuuuaaaargh! Ooh!";
break;
case 5:
return "Ooooaaaargh!";
break;
case 6:
return "Make this pain stop, please!";
break;
}
// This is an impossible case. Just here to keep the compiler happy.
return "This moan script sucks and WWWWolf is an idiot! AAAAaaaaAargh!";
}
void main()
{
object x;
int n;
int a;
string moan;
// Count the patients.
// n = HowManyWithTag(PATIENT);
// Let's do 1d4 moaning patients
int nmoans = d4(1);
for(a = 0; a < nmoans; a++) {
// Get a random patient
x = RandomPatient();
if(x == OBJECT_INVALID)
continue;
// Pick a random moaning
moan = RandomMoaning();
// Make the patient moan.
// AssignCommand(x, ActionSpeakString(moan));
AssignCommand(x, SpeakString(moan));
}
}

View File

@@ -0,0 +1,77 @@
/* Temple monk heartbeat script. Makes the monk do various combat
exercises, and meditate. Hiyyyyaaaaaaaa---ha! *CRACK* *CRASH*
Most of the ActionSpeakString()s in this thing are for debugging
purposes only and are not especially interesting for other uses.
WWWWolf 2003-10-29, for Dakanon
*/
#include "temple_fun"
const string STAFF = "TempleMonkStaff";
const string TARGET = "TempleMonkDummy";
void main()
{
/* Run normal heartbeat stuff */
NormalHeartbeat();
//ExecuteScript("nw_c2_default1",OBJECT_SELF);
/* This is the Staff. */
object staff = GetObjectByTag(STAFF);
/* This is the Target. */
object target = GetObjectByTag(TARGET);
/* Are we in combat? */
int incombat = GetIsInCombat();
/* Are we in conversation? Let's return, if so... */
if(IsInConversation(OBJECT_SELF)) {
return;
}
/* Equip/Unequip the staff ocassionally. */
if(d10(1) == 1) {
if(incombat)
ClearAllActions(TRUE); /* Quit attacking for a while */
//ActionSpeakString("To staff or not to staff, that is the question!");
if(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND) != staff)
ActionEquipItem(staff,INVENTORY_SLOT_RIGHTHAND);
else
ActionUnequipItem(staff);
if(incombat) /* Okay, switched, keep attacking... */
ActionAttack(target);
}
/* Attack - or quit attacking - the dummy ocassionally. */
if(!incombat) {
if(d10(1) == 1) {
//ActionSpeakString("Ryaaaaagh! Die, dummy!");
/* Attack the dummy. */
ActionAttack(target);
} else {
//ActionSpeakString("Cannot kill a harmless dummy!");
if(d6(1) <= 2) {
/* Sometimes, sit down and meditate. */
ActionSpeakString("Ommmmmmmmmmmmm....");
ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS,1.0, 8.0);
}
}
} else {
ActionAttack(target);
if(d10(1) == 1) {
/* Quit attacking the dummy. */
ClearAllActions(TRUE);
//ActionSpeakString("Shan't attack no more!");
} else {
//ActionSpeakString("Move like the water, strike like the thunder! "+
// "Attack like a raging bull!");
}
}
}

View File

@@ -0,0 +1,7 @@
#include "temple_fun"
void main()
{
CastSpellOnPC(SPELL_NEUTRALIZE_POISON, 200);
}

View File

@@ -0,0 +1,4 @@
void main()
{
PlayAnimation(ANIMATION_LOOPING_DEAD_FRONT,1.0,8.0);
}

View File

@@ -0,0 +1,59 @@
//:://////////////////////////////////////////////////
//:: CUSTOM OnSpawn handler.
#include "x0_i0_anims"
//#include "x0_i0_walkway"
#include "x0_i0_treasure"
void main()
{
// SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
// SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
// SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
// SetSpawnInCondition(NW_FLAG_STEALTH);
// SetSpawnInCondition(NW_FLAG_SEARCH);
// SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
// SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
// SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
// SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
// SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
// SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
// SetCombatCondition(X0_COMBAT_FLAG_RANGED);
// SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE);
// SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER);
// SetCombatCondition(X0_COMBAT_FLAG_COWARDLY);
// SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);
// SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);
// SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);
// SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);
// SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT);
// SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT);
// SetSpawnInCondition(NW_FLAG_ATTACK_EVENT);
// SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT);
// SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT);
// SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT);
// SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT);
SetListeningPatterns();
// WalkWayPoints();
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF);
// ***** ADD ANY CUSTOM ON-SPAWN CODE HERE ***** //
ApplyEffectToObject(DURATION_TYPE_INSTANT,
EffectDamage(GetCurrentHitPoints(OBJECT_SELF)-1, DAMAGE_TYPE_DIVINE),
OBJECT_SELF);
// Will this make it less laggy?
//PlayAnimation(ANIMATION_LOOPING_DEAD_FRONT,1.0,8.0);
}

View File

@@ -0,0 +1,6 @@
// Patient conversation script.
void main()
{
// Normal conversation isn't launched.
ActionSpeakString("Aaaaaaaargh.");
}

View File

@@ -0,0 +1,4 @@
void main()
{
PlayAnimation(ANIMATION_LOOPING_DEAD_BACK,1.0,8.0);
}

View File

@@ -0,0 +1,59 @@
//:://////////////////////////////////////////////////
//:: CUSTOM OnSpawn handler.
#include "x0_i0_anims"
//#include "x0_i0_walkway"
#include "x0_i0_treasure"
void main()
{
// SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
// SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
// SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
// SetSpawnInCondition(NW_FLAG_STEALTH);
// SetSpawnInCondition(NW_FLAG_SEARCH);
// SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
// SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
// SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
// SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
// SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
// SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
// SetCombatCondition(X0_COMBAT_FLAG_RANGED);
// SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE);
// SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER);
// SetCombatCondition(X0_COMBAT_FLAG_COWARDLY);
// SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);
// SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);
// SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);
// SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);
// SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT);
// SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT);
// SetSpawnInCondition(NW_FLAG_ATTACK_EVENT);
// SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT);
// SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT);
// SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT);
// SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT);
SetListeningPatterns();
// WalkWayPoints();
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF);
// ***** ADD ANY CUSTOM ON-SPAWN CODE HERE ***** //
ApplyEffectToObject(DURATION_TYPE_INSTANT,
EffectDamage(GetCurrentHitPoints(OBJECT_SELF)-1, DAMAGE_TYPE_DIVINE),
OBJECT_SELF);
// Will this make it less laggy?
//PlayAnimation(ANIMATION_LOOPING_DEAD_FRONT,1.0,8.0);
}

View File

@@ -0,0 +1,20 @@
/*
Sickbay receptionist heartbeat
Make her sit on the chair.
WWWWolf 2003-11-09
*/
#include "temple_fun"
void main()
{
NormalHeartbeat();
if(TooBusyToConverse())
return;
object chair = GetObjectByTag("NurseChair");
ActionSit(chair);
SetFacing(GetFacing(chair)); // Strange rotations and stuff.
}

View File

@@ -0,0 +1,67 @@
/*
Surgeon heartbeat. Make sure the dude is facing the operation table
and spouts random jargon.
WWWWolf 2003-11-09
*/
#include "temple_fun"
void main()
{
NormalHeartbeat();
if(TooBusyToConverse())
return;
// Make sure the surgeon is at his waypoint - to make sure he
// keeps smashing his hands to correct direction
// even if he turns around to babble.
FaceToMyLocation();
// Mutter various pieces of surgical jargon.
switch(d12(1)) {
default:
case 1:
ActionSpeakString("Scissors.");
break;
case 2:
ActionSpeakString("Scalpel.");
ActionPlayAnimation(ANIMATION_FIREFORGET_STEAL);
break;
case 3:
ActionSpeakString("Bone saw.");
ActionPlayAnimation(ANIMATION_FIREFORGET_STEAL);
break;
case 4:
ActionSpeakString("Hammer.");
break;
case 5:
ActionSpeakString("*tsk* *tsk* Axe, please.");
break;
case 6:
ActionSpeakString("Knife.");
ActionPlayAnimation(ANIMATION_FIREFORGET_STEAL);
break;
case 7:
ActionSpeakString("3/8 size gouger.");
ActionPlayAnimation(ANIMATION_FIREFORGET_STEAL);
break;
case 8:
ActionSpeakString("Hook.");
ActionPlayAnimation(ANIMATION_FIREFORGET_STEAL);
break;
case 9:
ActionSpeakString("Lancet.");
break;
case 10:
ActionSpeakString("Needle and thread.");
break;
case 11:
ActionSpeakString("Okay, prepare for amputation.");
break;
case 12:
ActionSpeakString("Could you sharpen this one?");
break;
}
}

View File

@@ -0,0 +1,15 @@
/*
Random wandering.
WWWWolf 2003-10
*/
void main()
{
// Usual heartbeat stuff
ExecuteScript("nw_c2_default1",OBJECT_SELF);
// Walk wherever you want
if(!IsInConversation(OBJECT_SELF) && !GetIsInCombat())
ActionRandomWalk();
}