497 lines
16 KiB
Plaintext
497 lines
16 KiB
Plaintext
/* Updated, ripped off and generally ruined by orch :
|
|
I've change the way the script looks for the areas for successful or failed
|
|
fishing. You now need to set 2 variables on the holes waypoint both strings, one
|
|
called TsFishFailure and TsFishSuccess the vaule is the name of the waypoint
|
|
for these areas.
|
|
*/
|
|
/*
|
|
ts_fishing
|
|
by Tseramed, aka Ken Demarest
|
|
(c) 2003 - Free to use. Must give author credit.
|
|
|
|
This script from the module 'Foreboding in Sylvani'
|
|
|
|
This fishing uses bait, casts (with animated splash), makes the
|
|
PC comment while waiting, and catches a variety of things. Also
|
|
included are fishing rods, bait, and a 'fish splashing' script
|
|
so that you know they're out there.
|
|
|
|
Includes a variety of templates for useful fish and useless stuff
|
|
you might accidentally catch.
|
|
|
|
You can customize what gets caught very easily. The 'success' and
|
|
'failure' stuff is kept in 'holding areas', each about 10'x10' and
|
|
isolated from the rest of the map. One holding area should have
|
|
a waypoint called 'TsFishSuccess', and the other 'TsFishFailure'
|
|
|
|
Just drop whatever items you want the player to catch, in whatever
|
|
proportion you want the stuff caught, within 10' of each waypoint.
|
|
You can put the holding areas in an area all their own, if you are
|
|
worried about players seeing them on their maps.
|
|
|
|
You can customize what gets caught in each area, or in different
|
|
fishing holes in the same area. When the code searches for the
|
|
TsFishSuccess and TsFishFailure waypoints, it looks for the
|
|
nearest ones first, and uses them in preference to ones farther
|
|
away.
|
|
|
|
A big nod to Nouny for this. Even though I didn't use his script,
|
|
I wouldn't have written this if it weren't for his efforts.
|
|
|
|
*/
|
|
|
|
//Added colors in messages...
|
|
//Ba'al
|
|
#include "gen_inc_color"
|
|
#include "prc_inc_racial"
|
|
|
|
const int TS_CHANCE_TO_CATCH = 94; // % chance to catch something.
|
|
const int CHANCE_OF_JACKPOT = 5000;
|
|
|
|
const string EEL_SHOCK = "ElectricEelShock";
|
|
|
|
const float holeMaxDist = 15.0;
|
|
|
|
float fRand( float max ) {
|
|
int n = Random(10000);
|
|
return IntToFloat(n) / 10000.0 * max;
|
|
}
|
|
|
|
|
|
// function for debugging
|
|
void tell( string s ) {
|
|
// SendMessageToPC( GetFirstPC(), s );
|
|
}
|
|
|
|
int near( object thing1, object thing2, float maxDist ) {
|
|
float dist = GetDistanceBetweenLocations( GetLocation(thing1), GetLocation(thing2) );
|
|
if( !GetIsObjectValid( thing1 ) )
|
|
return 0;
|
|
if( !GetIsObjectValid( thing2 ) )
|
|
return 0;
|
|
if( dist < 0.0 )
|
|
return 0;
|
|
if( dist > maxDist )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
string getPronoun( string s ) {
|
|
string firstLetter = GetStringLowerCase(GetStringLeft(s,1));
|
|
if( firstLetter == "a" ||
|
|
firstLetter == "e" ||
|
|
firstLetter == "i" ||
|
|
firstLetter == "o" ||
|
|
firstLetter == "u" )
|
|
return "an "+s;
|
|
return "a "+s;
|
|
}
|
|
|
|
void setBusy() {
|
|
SetLocalInt( OBJECT_SELF, "tsIsFishing", 1 );
|
|
}
|
|
|
|
void clrBusy() {
|
|
SetLocalInt( OBJECT_SELF, "tsIsFishing", 0 );
|
|
}
|
|
|
|
int isBusy() {
|
|
return GetLocalInt( OBJECT_SELF, "tsIsFishing" );
|
|
}
|
|
|
|
object pickFromHoldingArea( string wpTag, int objectType ) {
|
|
|
|
object wp = GetNearestObjectByTag( wpTag, OBJECT_SELF );
|
|
if( !GetIsObjectValid(wp) ) {
|
|
wp = GetWaypointByTag( wpTag );
|
|
}
|
|
if( !GetIsObjectValid(wp) ) {
|
|
SendMessageToPC( GetFirstPC(), "ERROR: A waypoint with the tag '"+wpTag+"' does not exist." );
|
|
return OBJECT_INVALID;
|
|
}
|
|
|
|
// Build the list of all combatants.
|
|
if( !GetLocalInt( wp, "tsTemplateCount" ) ) {
|
|
int done = 0;
|
|
int count = 0;
|
|
while( !done ) {
|
|
object who = GetNearestObject( objectType, wp, count+1 );
|
|
if( GetIsObjectValid(who) && GetDistanceBetween( wp, who ) < 9.5 ) {
|
|
SetLocalObject( wp, "tsTemplate"+IntToString(count), who );
|
|
int frequency = GetLocalInt( wp, "tsFrequency"+GetTag(who) );
|
|
++frequency;
|
|
SetLocalInt( wp, "tsFrequency"+GetTag(who), frequency );
|
|
++count;
|
|
}
|
|
else
|
|
done = 1;
|
|
}
|
|
SetLocalInt( wp, "tsTemplateCount", count );
|
|
|
|
// debug
|
|
tell( "tsTemplateCount = " + IntToString(count));
|
|
}
|
|
|
|
int index = Random( GetLocalInt( wp, "tsTemplateCount" ) );
|
|
return GetLocalObject( wp, "tsTemplate"+IntToString(index) );
|
|
}
|
|
|
|
|
|
void flash() {
|
|
effect e = EffectVisualEffect( 204 );
|
|
ApplyEffectToObject( DURATION_TYPE_TEMPORARY, e, OBJECT_SELF );
|
|
}
|
|
|
|
void callBack( object who ) {
|
|
tell( "Calling back to "+GetName(who) );
|
|
ExecuteScript( "ts_fishingwell", who );
|
|
}
|
|
|
|
void incState() {
|
|
int state = GetLocalInt( OBJECT_SELF, "tsFishingState" );
|
|
++state;
|
|
SetLocalInt( OBJECT_SELF, "tsFishingState", state );
|
|
}
|
|
void clrState() {
|
|
SetLocalInt( OBJECT_SELF, "tsFishingState", 0 );
|
|
SetLocalInt( OBJECT_SELF, "tsFishingReps", 0 );
|
|
}
|
|
|
|
int isRod( object what ) {
|
|
if( GetIsObjectValid(what) && ( GetTag(what)=="TsFishingRod" || GetTag(what)=="TsShortFishingRod" ) ) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
object getRod( object pc ) {
|
|
object rod = GetItemPossessedBy( pc, "TsFishingRod" );
|
|
if( ( MyPRCGetRacialType( pc ) == RACIAL_TYPE_HALFLING || MyPRCGetRacialType( pc ) == RACIAL_TYPE_GNOME ) ||
|
|
( !GetIsObjectValid( rod ) ) ) {
|
|
rod = GetItemPossessedBy( pc, "TsShortFishingRod" );
|
|
}
|
|
return rod;
|
|
}
|
|
|
|
void pcUnequipRod( object pc ) {
|
|
object inHand = GetItemInSlot( INVENTORY_SLOT_RIGHTHAND, pc );
|
|
if( isRod( inHand ) ) {
|
|
AssignCommand( pc, ActionUnequipItem( inHand ) );
|
|
}
|
|
}
|
|
|
|
void pcEquipRod( object pc, object rod ) {
|
|
object inHand = GetItemInSlot( INVENTORY_SLOT_RIGHTHAND, pc );
|
|
if( !isRod( inHand ) ) {
|
|
AssignCommand( pc, ActionEquipItem( rod, INVENTORY_SLOT_RIGHTHAND ) );
|
|
}
|
|
}
|
|
|
|
void invisSplash( object pc, object rod ) {
|
|
location loc = GetLocation( pc );
|
|
vector pos = GetPositionFromLocation( loc );
|
|
float facing = GetFacingFromLocation( loc )+(fRand(20.0)-10.0);
|
|
float splashDistance = 3.0+fRand(5.0); // est of player vision distance
|
|
pos.x += cos(facing) * splashDistance;
|
|
pos.y += sin(facing) * splashDistance;
|
|
loc = Location( GetAreaFromLocation(loc), pos, facing );
|
|
|
|
effect e = EffectVisualEffect( 93 );
|
|
ApplyEffectAtLocation( DURATION_TYPE_TEMPORARY, e, loc );
|
|
PlaySound( "as_na_splash2" );
|
|
DestroyObject( OBJECT_SELF, 2.0 );
|
|
}
|
|
|
|
string getCastSpeech() {
|
|
switch( Random(6) ) {
|
|
case 0: return GetRGB(1,15,15) + "Nice cast...";
|
|
case 1: return GetRGB(1,15,15) + "Good cast.";
|
|
case 2: return GetRGB(1,15,15) + "Cast could have been longer...";
|
|
case 3: return GetRGB(1,15,15) + "This cast was a bit left...";
|
|
case 4: return GetRGB(1,15,15) + "I made the cast.";
|
|
case 5: return GetRGB(1,15,15) + "That cast was precise.";
|
|
}
|
|
return GetRGB(1,15,15) + "Nice cast...";
|
|
}
|
|
|
|
string getWaitSpeech() {
|
|
switch( Random(6) ) {
|
|
case 0: return GetRGB(1,15,15) + "Hope I catch something.";
|
|
case 1: return GetRGB(1,15,15) + "Hope I get a nice fish.";
|
|
case 2: return GetRGB(1,15,15) + "I wonder if there are any eels here?";
|
|
case 3: return GetRGB(1,15,15) + "How long before I get a bite?";
|
|
case 4: return GetRGB(1,15,15) + "Was that a nibble?";
|
|
case 5: return GetRGB(1,15,15) + "Ho hum...";
|
|
}
|
|
return GetRGB(1,15,15) + "Hope I catch something.";
|
|
}
|
|
|
|
void pcSplash( object pc, object rod ) {
|
|
|
|
location loc = GetLocation( pc );
|
|
object invis = CreateObject( OBJECT_TYPE_PLACEABLE, "plc_invisobj", loc );
|
|
DelayCommand( 1.0, invisSplash( pc, rod ) );
|
|
|
|
DelayCommand( 4.0, AssignCommand( pc, SpeakString( getCastSpeech() ) ) );
|
|
DelayCommand( 11.0, AssignCommand( pc, SpeakString( getWaitSpeech() ) ) );
|
|
}
|
|
|
|
void initFishing() {
|
|
object pc = GetItemActivator();
|
|
if( !GetIsObjectValid( pc ) )
|
|
return;
|
|
|
|
AssignCommand( pc, ClearAllActions() );
|
|
|
|
object rod = getRod( pc );
|
|
|
|
if( !GetIsObjectValid( rod ) ) {
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "I need a fishing rod to fish." ) );
|
|
AssignCommand( pc, ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD , 1.0, 2.0) );
|
|
return;
|
|
}
|
|
int IsPCFishing = GetLocalInt(rod,"IsPCFishing");
|
|
|
|
// debug
|
|
tell( "IsPCFishing = " + IntToString(IsPCFishing));
|
|
|
|
if (IsPCFishing != 1)
|
|
{
|
|
//ok to start fishing
|
|
SetLocalInt(rod,"IsPCFishing",1);
|
|
}
|
|
else {
|
|
SetLocalInt(rod,"IsPCFishing",0);
|
|
return;
|
|
}
|
|
object hole = GetNearestObjectByTag( "TsFishingHole", pc );
|
|
|
|
if( !near( pc, hole, holeMaxDist ) ) {
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "There is no obvious place to fish." ) );
|
|
AssignCommand( pc, ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD , 1.0, 2.0) );
|
|
AssignCommand( pc, ActionDoCommand( pcUnequipRod( pc ) ) );
|
|
|
|
// elvin - reset fishing status if not near hole
|
|
SetLocalInt(rod,"IsPCFishing",0);
|
|
return;
|
|
}
|
|
|
|
SetLocalObject( OBJECT_SELF, "tsPc", pc );
|
|
SetLocalObject( OBJECT_SELF, "tsRod", rod );
|
|
SetLocalObject( OBJECT_SELF, "tsHole", hole );
|
|
|
|
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "I think I'll drop a line..." ) );
|
|
|
|
setBusy();
|
|
incState();
|
|
callBack( OBJECT_SELF );
|
|
}
|
|
|
|
void prepareToFish() {
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
object hole = GetLocalObject( OBJECT_SELF, "tsHole" );
|
|
object rod = GetLocalObject( OBJECT_SELF, "tsRod" );
|
|
object bait = OBJECT_SELF;
|
|
if( GetTag(bait) != "FishingBait" ) {
|
|
tell( "Bait is "+GetName(bait) );
|
|
}
|
|
|
|
incState();
|
|
|
|
AssignCommand( pc, ActionMoveToLocation( GetLocation( hole ), TRUE ) );
|
|
|
|
// CAST LINE
|
|
AssignCommand( pc, ActionDoCommand( SetFacing( GetFacingFromLocation( GetLocation(hole) ) ) ) );
|
|
AssignCommand( pc, ActionDoCommand( pcEquipRod( pc, rod ) ) );
|
|
AssignCommand( pc, ActionWait( 2.0 ) );
|
|
AssignCommand( pc, ActionDoCommand( pcSplash( pc, rod ) ) );
|
|
AssignCommand( pc, ActionPlayAnimation( ANIMATION_LOOPING_LISTEN, 0.1, 6.0 ) );
|
|
AssignCommand( pc, ActionWait( 1.0 ) );
|
|
AssignCommand( pc, ActionDoCommand( callBack( bait ) ) );
|
|
}
|
|
|
|
|
|
object catchResult( object makeThis, string sayThis ) {
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
|
|
object thing = CopyObject( makeThis, GetLocation(pc) );
|
|
effect e = EffectVisualEffect( 284 );
|
|
ApplyEffectToObject( DURATION_TYPE_TEMPORARY, e, OBJECT_SELF );
|
|
|
|
AssignCommand( pc, SpeakString( sayThis ) );
|
|
if( GetObjectType(thing) == OBJECT_TYPE_ITEM ) {
|
|
AssignCommand( pc, DelayCommand( 2.0, ActionPickUpItem( thing ) ) );
|
|
}
|
|
return thing;
|
|
}
|
|
|
|
int testRodBreak() {
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
object rod = GetLocalObject( OBJECT_SELF, "tsRod" );
|
|
|
|
if( d100() < 1 ) {
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "Darn! I felt a tug, but my rod broke." ) );
|
|
DestroyObject( rod );
|
|
PlaySound( "as_na_branchsnp3" );
|
|
AssignCommand( pc, ActionPlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL , 1.0, 4.0 ) );
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*void goRotten( object what ) {
|
|
if( GetIsObjectValid( what ) ) {
|
|
object pc = GetItemPossessor( what );
|
|
if( GetIsObjectValid(pc) && GetIsPC(pc) ) {
|
|
if( GetIsInCombat(pc) || GetIsResting(pc) || IsInConversation(pc) ) {
|
|
DelayCommand( 6.0, goRotten(what) );
|
|
}
|
|
AssignCommand( pc, SpeakString( "My "+GetName(what)+" just rotted away." ) );
|
|
}
|
|
DestroyObject( what );
|
|
}
|
|
} */
|
|
|
|
void fishingResult() {
|
|
clrState();
|
|
clrBusy();
|
|
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
object hole = GetLocalObject( OBJECT_SELF, "tsHole" );
|
|
|
|
//int nDexMod = GetAbilityModifier( ABILITY_DEXTERITY, pc );
|
|
// int nWisMod = GetAbilityModifier( ABILITY_WISDOM, pc );
|
|
|
|
location lLoc = GetLocation( pc );
|
|
|
|
if( testRodBreak() ) {
|
|
return;
|
|
}
|
|
|
|
if( d100() < 20 /*- (nDexMod+nWisMod)*3*/ ) {
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "I did not catch anything." ) );
|
|
}
|
|
else
|
|
{
|
|
string TsSuccess = GetLocalString( hole,"TsFishSuccess");
|
|
string TsFail = GetLocalString (hole , "TsFishFailure");
|
|
string TsJackpot = GetLocalString (hole , "TsFishJackpot");
|
|
if (TsSuccess == "" || TsFail == "" || TsJackpot == "")
|
|
{
|
|
TsSuccess = "TsFishSuccess";
|
|
TsFail = "TsFishFailure";
|
|
TsJackpot = "TsFishJackpot";
|
|
}
|
|
// Fish
|
|
if( d100() < TS_CHANCE_TO_CATCH ) {
|
|
|
|
object template;
|
|
if( Random(CHANCE_OF_JACKPOT) == (CHANCE_OF_JACKPOT/2) )
|
|
{
|
|
template = pickFromHoldingArea( TsJackpot, OBJECT_TYPE_ITEM );
|
|
object what = catchResult( template, GetRGB(1,15,15) + "Woohoo! I'm rich! I've caught " + GetName(template) );
|
|
}
|
|
else
|
|
{
|
|
template = pickFromHoldingArea( TsSuccess, OBJECT_TYPE_ITEM );
|
|
object what = catchResult( template, GetRGB(1,15,15) + "I caught "+getPronoun(GetStringLowerCase(GetName(template))) );
|
|
}
|
|
//DelayCommand( 6.0 * 2.0/*10.0 * 5.0*/, goRotten( what ) );
|
|
}
|
|
else {
|
|
object template = pickFromHoldingArea( TsFail, OBJECT_TYPE_ITEM | OBJECT_TYPE_CREATURE );
|
|
|
|
// Elvin - Eel shock test, and effect/damage
|
|
if( GetTag(template) == EEL_SHOCK )
|
|
{
|
|
effect eElectricShockDamage = EffectDamage(300, DAMAGE_TYPE_ELECTRICAL);
|
|
effect eElectricShockVisual = EffectVisualEffect(VFX_COM_HIT_ELECTRICAL);
|
|
effect eLink = EffectLinkEffects(eElectricShockDamage, eElectricShockVisual);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, pc);
|
|
|
|
AssignCommand( pc, SpeakString( GetRGB(1,15,15) + "Yikes! I disturbed an electric eel!" ) );
|
|
}
|
|
else
|
|
{
|
|
catchResult( template, GetRGB(1,15,15) + "Oh crap! I caught "+getPronoun(GetStringLowerCase(GetName(template))) );
|
|
}
|
|
}
|
|
}
|
|
|
|
DestroyObject( OBJECT_SELF, 1.0 );
|
|
object rod = GetLocalObject( OBJECT_SELF, "tsRod" );
|
|
SetLocalInt(rod,"IsPCFishing",0);
|
|
}
|
|
|
|
int confirmState( int state ) {
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
object hole = GetLocalObject( OBJECT_SELF, "tsHole" );
|
|
object rod = GetLocalObject( OBJECT_SELF, "tsRod" );
|
|
|
|
if( state > 0 ) {
|
|
if( !GetIsObjectValid(pc) || !GetIsObjectValid(hole) || !GetIsObjectValid(rod) ) {
|
|
tell( "reset state to 0" );
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if( state > 0 ) {
|
|
object rod = getRod( pc );
|
|
if( !GetIsObjectValid( rod ) ) {
|
|
tell( "halted - no rod" );
|
|
return 99;
|
|
}
|
|
|
|
object hole = GetNearestObjectByTag( "TsFishingHole", pc );
|
|
|
|
if( !near( pc, hole, holeMaxDist ) ) {
|
|
tell( "halted - no hole" );
|
|
return 99;
|
|
}
|
|
}
|
|
|
|
if( state > 1 ) {
|
|
// You must be near the hole.
|
|
// elvin - correct distance check
|
|
if( !near( pc, hole, holeMaxDist ) ) {
|
|
tell( "restart - not near hole" );
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
AssignCommand( pc, ClearAllActions() );
|
|
clrState();
|
|
return 0;
|
|
}
|
|
|
|
// You don't get to catch fish if you're not holding the rod.
|
|
object inHand = GetItemInSlot( INVENTORY_SLOT_RIGHTHAND, pc );
|
|
if( !isRod( inHand ) ) {
|
|
tell( "halted - rod ! in hand" );
|
|
return 99;
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
void main() {
|
|
int state = GetLocalInt( OBJECT_SELF, "tsFishingState" );
|
|
|
|
tell( GetName(OBJECT_SELF)+" state="+IntToString(state) );
|
|
state = confirmState( state );
|
|
SetLocalInt( OBJECT_SELF, "tsFishingState", state );
|
|
|
|
switch( state ) {
|
|
case 0: initFishing(); break;
|
|
case 1: prepareToFish(); break;
|
|
case 2: fishingResult(); break;
|
|
case 99: {
|
|
object pc = GetLocalObject( OBJECT_SELF, "tsPc" );
|
|
AssignCommand( pc, ClearAllActions() );
|
|
clrState();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|