Bugfix pass.
Fixed onRespawn & onDying scripts. Fixed XP awards. Added temple hospital & library.
This commit is contained in:
		
							
								
								
									
										12
									
								
								_module/nss/merc_templestore.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								_module/nss/merc_templestore.nss
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								_module/nss/merc_tmpl_check.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								_module/nss/merc_tmpl_check.nss
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								_module/nss/prc_pwondeath.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								_module/nss/prc_pwondeath.nss
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
@@ -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 !
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								_module/nss/temple_assisthb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								_module/nss/temple_assisthb.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
/*
 | 
			
		||||
    Operation assistant heartbeat.
 | 
			
		||||
 | 
			
		||||
    WWWWolf 2003-10-09
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    NormalHeartbeat();
 | 
			
		||||
 | 
			
		||||
    if(TooBusyToConverse())
 | 
			
		||||
        return;
 | 
			
		||||
    FaceToMyLocation();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_curecrit.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_curecrit.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_CURE_CRITICAL_WOUNDS, 200);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_curelight.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_curelight.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_CURE_LIGHT_WOUNDS, 50);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_fcurecrit.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_fcurecrit.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_CURE_CRITICAL_WOUNDS, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_fcurelig.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_fcurelig.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_CURE_LIGHT_WOUNDS, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_flessres.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_flessres.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_LESSER_RESTORATION, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_fneutpoi.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_fneutpoi.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_NEUTRALIZE_POISON, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								_module/nss/temple_fun.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								_module/nss/temple_fun.nss
									
									
									
									
									
										Normal 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								_module/nss/temple_has100gp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								_module/nss/temple_has100gp.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
int StartingConditional()
 | 
			
		||||
{
 | 
			
		||||
    if(GetGold(GetPCSpeaker()) >= 100)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								_module/nss/temple_has200gp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								_module/nss/temple_has200gp.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
int StartingConditional()
 | 
			
		||||
{
 | 
			
		||||
    if(GetGold(GetPCSpeaker()) >= 200)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								_module/nss/temple_has50gp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								_module/nss/temple_has50gp.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
int StartingConditional()
 | 
			
		||||
{
 | 
			
		||||
    if(GetGold(GetPCSpeaker()) >= 50)
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_lessresto.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_lessresto.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_LESSER_RESTORATION, 100);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										104
									
								
								_module/nss/temple_moaning.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								_module/nss/temple_moaning.nss
									
									
									
									
									
										Normal 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));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										77
									
								
								_module/nss/temple_monkhb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								_module/nss/temple_monkhb.nss
									
									
									
									
									
										Normal 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!");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								_module/nss/temple_neutrapoi.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								_module/nss/temple_neutrapoi.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
#include "temple_fun"
 | 
			
		||||
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    CastSpellOnPC(SPELL_NEUTRALIZE_POISON, 200);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								_module/nss/temple_patien2hb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								_module/nss/temple_patien2hb.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    PlayAnimation(ANIMATION_LOOPING_DEAD_FRONT,1.0,8.0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								_module/nss/temple_patien2sp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								_module/nss/temple_patien2sp.nss
									
									
									
									
									
										Normal 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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								_module/nss/temple_patientco.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								_module/nss/temple_patientco.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
// Patient conversation script.
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    // Normal conversation isn't launched.
 | 
			
		||||
    ActionSpeakString("Aaaaaaaargh.");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								_module/nss/temple_patienthb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								_module/nss/temple_patienthb.nss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
void main()
 | 
			
		||||
{
 | 
			
		||||
    PlayAnimation(ANIMATION_LOOPING_DEAD_BACK,1.0,8.0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								_module/nss/temple_patientsp.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								_module/nss/temple_patientsp.nss
									
									
									
									
									
										Normal 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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								_module/nss/temple_sbrechb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								_module/nss/temple_sbrechb.nss
									
									
									
									
									
										Normal 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.
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										67
									
								
								_module/nss/temple_surghb.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								_module/nss/temple_surghb.nss
									
									
									
									
									
										Normal 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								_module/nss/temple_wander.nss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								_module/nss/temple_wander.nss
									
									
									
									
									
										Normal 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();
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user