2944 lines
75 KiB
C
2944 lines
75 KiB
C
|
|
||
|
/******************************************************************************
|
||
|
|
||
|
SKIDROW - Episode specific code
|
||
|
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "g_local.h"
|
||
|
|
||
|
#include "voice_punk.h"
|
||
|
#include "voice_bitch.h"
|
||
|
|
||
|
void Pull_Alarm_Think (edict_t *ent);
|
||
|
qboolean EP_Skidrow_ProcessMagicJ( edict_t *self, edict_t *other, cast_memory_t *mem );
|
||
|
|
||
|
qboolean ProcessMomo (edict_t *self, edict_t *other);
|
||
|
void EP_skidrow_radio_on (edict_t *self);
|
||
|
|
||
|
void Resp_Lenny (edict_t *self, edict_t *other, response_t response);
|
||
|
|
||
|
//............................................................................
|
||
|
// This gets called whenever a character (player or AI) is sighted by an AI character
|
||
|
// in the Skidrow episode
|
||
|
|
||
|
// Returns TRUE if no further processing should take place in AI_RecordSighting()
|
||
|
|
||
|
qboolean EP_Skidrow_CastSight ( edict_t *self, edict_t *other, cast_memory_t *mem )
|
||
|
{
|
||
|
|
||
|
// Jesus (SR4 boss), if player gets battery, go into Psycho mode
|
||
|
if (self->name_index == NAME_JESUS && other->client && !(self->cast_info.aiflags & AI_NO_TAKE_COVER))
|
||
|
{
|
||
|
static int battery_index;
|
||
|
|
||
|
if (!battery_index)
|
||
|
battery_index = 1 + ITEM_INDEX(FindItem("Battery"));
|
||
|
|
||
|
if (other->client->pers.inventory[battery_index - 1])
|
||
|
{ // go into Psycho mode
|
||
|
self->cast_info.aiflags |= AI_NO_TAKE_COVER;
|
||
|
|
||
|
// gi.dprintf( "SOUND TODO: Leave that battery alone muthafucka!!\n" );
|
||
|
Voice_Specific (self, other, sr_jesus, 16);
|
||
|
|
||
|
// release if currently hiding
|
||
|
self->combat_goalent = NULL;
|
||
|
self->cast_info.aiflags &= ~AI_TAKE_COVER;
|
||
|
self->dont_takecover_time = 99999;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (self->name_index == NAME_RUMMY || self->name_index == NAME_NICK || self->name_index == NAME_ED)
|
||
|
{
|
||
|
if (self->name_index == NAME_RUMMY && other->client)
|
||
|
{
|
||
|
other->episode_flags &= ~EP_SKIDROW_RUMMY_ASKED_WINE;
|
||
|
}
|
||
|
|
||
|
if (other->client && (mem->memory_type == MEMORY_TYPE_ENEMY) && !(other->client->pers.weapon))
|
||
|
{ // give them a chance to make friends if they holster
|
||
|
self->enemy = NULL;
|
||
|
|
||
|
// make them a neutral instead of enemy
|
||
|
AI_RemoveFromMemory( self, mem );
|
||
|
AI_AddToMemory( self, mem, MEMORY_TYPE_NEUTRAL );
|
||
|
mem->flags &= ~MEMORY_HOSTILE_ENEMY;
|
||
|
}
|
||
|
// ignore them
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Ridah, 5-8-99, added this so Momo asks you for the money if he hasn't seen you for a while
|
||
|
if (self->name_index == NAME_MOMO && other->client)
|
||
|
{
|
||
|
if (mem->timestamp < (level.time - 8))
|
||
|
{ // haven't seen them for a while
|
||
|
other->episode_flags &= ~EP_SKIDROW_MOMO_ASKED_MONEY;
|
||
|
// mem->flags &= ~MEMORY_LASTWARNING;
|
||
|
}
|
||
|
|
||
|
if ((mem->memory_type == MEMORY_TYPE_ENEMY) /*&& !other->client->pers.weapon*/)
|
||
|
{ // give them a chance to make friends if they holster
|
||
|
self->enemy = NULL;
|
||
|
|
||
|
// make them a neutral instead of enemy
|
||
|
AI_RemoveFromMemory( self, mem );
|
||
|
AI_AddToMemory( self, mem, MEMORY_TYPE_NEUTRAL );
|
||
|
mem->flags &= ~MEMORY_HOSTILE_ENEMY;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Hack, don't let Mona talk, or it'll probably sound too "feminin"
|
||
|
if (self->name_index == NAME_MONA)
|
||
|
{
|
||
|
self->cast_info.aiflags |= AI_NO_TALK;
|
||
|
}
|
||
|
|
||
|
// Ridah, if listening to the radio, ignore player unless he's really close
|
||
|
if ( ( (self->name_index == NAME_BERNIE)
|
||
|
|| (self->name_index == NAME_ARNOLD))
|
||
|
&& (other->client)
|
||
|
&& (self->goal_ent && self->goal_ent->think == EP_skidrow_radio_on))
|
||
|
{
|
||
|
if (self->enemy)
|
||
|
{
|
||
|
self->goal_ent = NULL;
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (other->current_territory != self->cast_group || VectorDistance(self->s.origin, other->s.origin) > AI_NOT_HOLSTERED_RANGE_2)
|
||
|
{
|
||
|
// Ignore them
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (VectorDistance (self->s.origin, other->s.origin) > AI_NOT_HOLSTERED_RANGE_1)
|
||
|
{
|
||
|
// Dont get mad yet
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// too close waist em
|
||
|
AI_MakeEnemy( self, other, 0 );
|
||
|
AI_StartAttack( self, other );
|
||
|
self->goal_ent = NULL;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (self->name_index == NAME_LAMONT)
|
||
|
{
|
||
|
float dist;
|
||
|
|
||
|
if (self->enemy) // currently attacking
|
||
|
{
|
||
|
self->cast_info.aiflags |= AI_NO_TALK;
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
self->cast_info.aiflags &= ~AI_NO_TALK;
|
||
|
}
|
||
|
|
||
|
dist = VectorDistance(self->s.origin, other->s.origin);
|
||
|
|
||
|
self->cast_info.aiflags |= AI_FASTWALK;
|
||
|
|
||
|
// check if player has entered range 1
|
||
|
if (other->client)
|
||
|
{
|
||
|
if (dist < AI_NOT_HOLSTERED_RANGE_1)
|
||
|
{
|
||
|
if (mem->inc < 10)
|
||
|
{ // we've come from outside the range
|
||
|
if (mem->inc < 4)
|
||
|
mem->inc++;
|
||
|
|
||
|
mem->inc += 10; // signify that we are now inside the range
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (mem->inc >= 10)
|
||
|
{ // just left the range 1
|
||
|
mem->inc -= 10;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (VectorDistance( self->s.origin, g_edicts[1].s.origin ) < AI_NOT_HOLSTERED_RANGE_1)
|
||
|
{ // talk to the player since they're close by
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// now talk if we're standing around
|
||
|
if ( (self->last_talk_time < (level.time - 3))
|
||
|
&& ( (self->cast_info.currentmove->frame->aifunc == ai_stand)
|
||
|
|| (other->client && dist < AI_NOT_HOLSTERED_RANGE_1/2)))
|
||
|
{ // Lamont's a nut case..
|
||
|
|
||
|
if (dist < AI_NOT_HOLSTERED_RANGE_1/2)
|
||
|
self->cast_info.pausetime = level.time + 2;
|
||
|
|
||
|
if (other->client && (dist < AI_NOT_HOLSTERED_RANGE_1)) // talk shit to player
|
||
|
{
|
||
|
// client is close, act hostile
|
||
|
|
||
|
if (mem->inc%10 >= 4)
|
||
|
{ // attack
|
||
|
AI_MakeEnemy( self, other, 0 );
|
||
|
Voice_Specific( self, other, lamont_random, 14 );
|
||
|
}
|
||
|
|
||
|
if ( (lamont_random[10 + mem->inc%10].last_played < (level.time - 10))
|
||
|
|| (lamont_random[10 + mem->inc%10].last_played > level.time))
|
||
|
{
|
||
|
Voice_Specific( self, other, lamont_random, 10 + mem->inc%10 );
|
||
|
}
|
||
|
else // randomly abuse player, and go on about Lenny
|
||
|
{
|
||
|
Voice_Random( self, other, &lamont_random[6], 7 );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (!(other->client))
|
||
|
{
|
||
|
Voice_Random( self, other, lamont_random, 6 );
|
||
|
}
|
||
|
else // they are a client, but a good distance away
|
||
|
{
|
||
|
Voice_Random( self, other, &lamont_random[0], 9 );
|
||
|
}
|
||
|
|
||
|
if ((dist < AI_NOT_HOLSTERED_RANGE_1) && !directly_infront( self, other))
|
||
|
self->cast_info.avoid( self, other, true );
|
||
|
else
|
||
|
self->cast_info.talk( self );
|
||
|
|
||
|
// pick a random path_corner to go to next
|
||
|
if (self->goal_ent && self->goal_ent->target)
|
||
|
{
|
||
|
edict_t *trav=NULL;
|
||
|
int i;
|
||
|
|
||
|
i = rand()%4;
|
||
|
|
||
|
while (i-- && self->goal_ent->target && (trav = G_PickTarget(self->goal_ent->target)))
|
||
|
{
|
||
|
self->goal_ent = trav;
|
||
|
}
|
||
|
|
||
|
self->goal_ent->wait = 1 + rand()%4;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (self->goal_ent && !self->goal_ent->wait)
|
||
|
self->goal_ent->wait = 1 + rand()%4;
|
||
|
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
// Ridah, play Beth's special "backoff"
|
||
|
if ( self->name_index == NAME_BETH && other->client && (self->last_talk_time < (level.time - 3)) )
|
||
|
{
|
||
|
if ( (!(other->client->pers.holsteredweapon))
|
||
|
&& (other->client->pers.weapon)
|
||
|
&& (!(mem->flags & MEMORY_WARNED_BACKOFF)))
|
||
|
{
|
||
|
float dist;
|
||
|
|
||
|
dist = VectorDistance( self->s.origin, other->s.origin );
|
||
|
|
||
|
if (dist < AI_NOT_HOLSTERED_RANGE_2)
|
||
|
{
|
||
|
mem->flags |= MEMORY_WARNED_BACKOFF;
|
||
|
Voice_Random(self, other, &beth_specific[7], 2);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( self->name_index == NAME_MAGICJ && other->client)
|
||
|
{
|
||
|
|
||
|
if ( !(other->client->pers.holsteredweapon) )
|
||
|
{
|
||
|
mem->flags |= MEMORY_AFRAID;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
self->cast_info.aiflags &= ~AI_NO_TALK;
|
||
|
mem->flags &= ~MEMORY_AFRAID;
|
||
|
}
|
||
|
|
||
|
return EP_Skidrow_ProcessMagicJ (self, other, mem);
|
||
|
}
|
||
|
|
||
|
if ( self->cast_group == GANG_RATGANG )
|
||
|
{
|
||
|
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
|
||
|
|
||
|
if (other->client && !(other->episode_flags & EP_SKIDROW_RATS_PISSED))
|
||
|
{
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_RATS_PISSED);
|
||
|
}
|
||
|
|
||
|
if (mem->flags & MEMORY_TAUNT && last_client_talk > level.time)
|
||
|
{
|
||
|
mem->flags &= ~MEMORY_TAUNT;
|
||
|
|
||
|
Voice_Random(self, self->cast_info.talk_ent, profanity_level2, NUM_PROFANITY_LEVEL2);
|
||
|
last_client_talk = level.time + 3 + rand()%10;
|
||
|
|
||
|
self->cast_info.currentmove = self->cast_info.move_stand;
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//............................................................................
|
||
|
// EP_Skidrow_CastUse
|
||
|
// Called when ever a character is "used" (like when someone dies)
|
||
|
|
||
|
qboolean EP_Skidrow_CastUse (edict_t *self, edict_t *other, edict_t *activator)
|
||
|
{
|
||
|
|
||
|
if ((other->name_index == NAME_LOUIE) && (other->health <= 0))
|
||
|
{ // Louie has been killed, so walk to him
|
||
|
self->goal_ent = other;
|
||
|
self->target = NULL;
|
||
|
|
||
|
other->cast_info.aiflags |= AI_GOAL_RUN; // Run to him
|
||
|
|
||
|
// gi.dprintf( "Louie has been killed, sending Al in to investigate\n" );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//............................................................................
|
||
|
// EP_Skidrow_EventSpeech
|
||
|
// Called on speech occasions (including flashlight hitting player)
|
||
|
//
|
||
|
// Return TRUE so that the normal speech routines don't say something as well
|
||
|
|
||
|
qboolean EP_Skidrow_EventSpeech (edict_t *self, edict_t *other, int saywhat)
|
||
|
{
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
|
||
|
|
||
|
|
||
|
//............................................................................
|
||
|
// LAMONT
|
||
|
if ( self->name_index == NAME_LAMONT )
|
||
|
{ // Lamont speech done in EP_CastSight()
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Hack, record that we've been to the Bar
|
||
|
if (other->client && level.bar_lvl)
|
||
|
{
|
||
|
// other->client->pers.episode_flags = other->episode_flags |= EP_BAR_FIRST_TIME;
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_BAR_FIRST_TIME);
|
||
|
}
|
||
|
|
||
|
switch (saywhat)
|
||
|
{
|
||
|
|
||
|
case say_neutral:
|
||
|
|
||
|
if (self->name_index == NAME_RUMMY && other->client)
|
||
|
{
|
||
|
if (other->episode_flags & EP_SKIDROW_RUMMY_GAVE_WINE)
|
||
|
{
|
||
|
Voice_Random (self, other, &rummy[14], 2);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_TALKED_TO_RUMMY) && !(self->episode_flags & EP_SKIDROW_RUMMY_GAVE_WINE))
|
||
|
{
|
||
|
mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
|
||
|
|
||
|
Voice_Random (self, other, &rummy[8], 2);
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_TALKED_TO_RUMMY);
|
||
|
mem->response = Resp_Rummy_GotWine;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else if (!(other->episode_flags & EP_SKIDROW_RUMMY_ASKED_WINE) && !(self->episode_flags & EP_SKIDROW_RUMMY_GAVE_WINE))
|
||
|
{
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
{
|
||
|
Voice_Random (self, other, &rummy[8], 2);
|
||
|
// other->episode_flags |= EP_SKIDROW_RUMMY_ASKED_WINE;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_RUMMY_ASKED_WINE;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_RUMMY_ASKED_WINE);
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_TALKED_TO_RUMMY);
|
||
|
mem->response = Resp_Rummy_GotWine;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// have they responded yet?
|
||
|
else if ( (other->response_ent == self)
|
||
|
&& (other->last_response_time > (level.time - 5)))
|
||
|
{
|
||
|
|
||
|
if (other->last_response == resp_yes)
|
||
|
{
|
||
|
int index;
|
||
|
gitem_t *item;
|
||
|
|
||
|
Voice_Random ( self, other, &rummy[4], 2 );
|
||
|
// gi.dprintf ("Rummy: the combination is 36 26 36 ... \n");
|
||
|
|
||
|
item = FindItem ("Whiskey");
|
||
|
index = ITEM_INDEX (item);
|
||
|
other->client->pers.inventory[ index ] = 0;
|
||
|
// show icon and name on status bar
|
||
|
other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(item->icon);
|
||
|
other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+index;
|
||
|
other->client->pickup_msg_time = level.time + 5.5;
|
||
|
|
||
|
// other->episode_flags |= EP_SKIDROW_RUMMY_GAVE_WINE;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_RUMMY_GAVE_WINE;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_RUMMY_GAVE_WINE);
|
||
|
|
||
|
{
|
||
|
edict_t *e;
|
||
|
int i;
|
||
|
|
||
|
for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
|
||
|
{
|
||
|
if ((e->targetname) && (!strcmp(e->targetname, "safedoor_sr")))
|
||
|
{
|
||
|
// Unlock target door
|
||
|
if (e->key == -1)
|
||
|
{
|
||
|
e->key = 0;
|
||
|
e->targetname = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random (self, other, &rummy[10], 2);
|
||
|
mem->response = Resp_Rummy_GotWine;
|
||
|
}
|
||
|
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
mem->response = NULL;
|
||
|
|
||
|
other->response_ent = NULL;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ask for wine
|
||
|
else if ( (specific[4].last_played < (level.time - 3))
|
||
|
&& (specific[9].last_played < (level.time - 4)))
|
||
|
{
|
||
|
Voice_Random ( self, other, &rummy[8], 2 );
|
||
|
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
mem->response = Resp_Rummy_GotWine;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
Voice_Random ( self, other, &rummy[12], 2);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (self->name_index == NAME_NICK && other->client)
|
||
|
{
|
||
|
if (!(other->episode_flags & EP_SKIDROW_NICK_TOLD_BIKE))
|
||
|
{
|
||
|
Voice_Specific (self, other, nick, 6);
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_TOLD_BIKE);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_NICK_WARNING_1))
|
||
|
{
|
||
|
Voice_Specific (self, other, nick, 0);
|
||
|
// other->client->pers.episode_flags = other->episode_flags |= EP_SKIDROW_JOSEPH_WARNING_1;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_WARNING_1);
|
||
|
}
|
||
|
else if (!(other->episode_flags & EP_SKIDROW_NICK_WARNING_2))
|
||
|
{
|
||
|
Voice_Random (self, other, &nick[1], 2);
|
||
|
// other->client->pers.episode_flags = other->episode_flags |= EP_SKIDROW_JOSEPH_WARNING_2;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_WARNING_2);
|
||
|
}
|
||
|
else if (!(other->episode_flags & EP_SKIDROW_NICK_WARNING_3))
|
||
|
{
|
||
|
Voice_Random (self, other, &nick[3], 2);
|
||
|
// other->client->pers.episode_flags = other->episode_flags |= EP_SKIDROW_JOSEPH_WARNING_3;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_WARNING_3);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific( self, other, nick, 5 );
|
||
|
other->client->pers.episode_flags = other->episode_flags &= ~EP_SKIDROW_NICK_WARNING_1;
|
||
|
other->client->pers.episode_flags = other->episode_flags &= ~EP_SKIDROW_NICK_WARNING_2;
|
||
|
other->client->pers.episode_flags = other->episode_flags &= ~EP_SKIDROW_NICK_WARNING_3;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (self->name_index == NAME_ED && other->client)
|
||
|
{
|
||
|
Voice_Random (self, other, rummy, 4);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (self->name_index == NAME_LENNY && other->client)
|
||
|
{
|
||
|
|
||
|
self->cast_info.aiflags |= AI_REPEAT_TALK_JESTURE;
|
||
|
|
||
|
// Have they got the watch?
|
||
|
if ((other->client->pers.inventory[ITEM_INDEX(FindItem("Watch"))]) ||
|
||
|
(other->episode_flags & EP_SKIDROW_LENNY_TOOK_WATCH))
|
||
|
{ // got the watch..
|
||
|
|
||
|
if (!(other->client->pers.inventory[ITEM_INDEX(FindItem("StoreRoomKey"))]))
|
||
|
{ // Lenny hasn't given the key yet..
|
||
|
|
||
|
if (mem->inc != 199) // we haven't praised them yet
|
||
|
{
|
||
|
if (other->client->pers.episode_flags & EP_TALKED_TO_LENNY)
|
||
|
{
|
||
|
Voice_Specific( self, other, lenny_table, 1 ); // that's great!
|
||
|
self->last_talk_time -= TALK_SELF_DELAY - 1.5; // only wait 1.5 before we speak again, regardless of whether they respond or not
|
||
|
other->last_talk_time = self->last_talk_time - 1; // must have this so we don't think they've said something after us as a result of the above hack
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific( self, other, lenny_table, 0 ); // christ, that's great!
|
||
|
self->last_talk_time -= TALK_SELF_DELAY - 4.5; // wait 4.5 seconds
|
||
|
other->last_talk_time = self->last_talk_time - 1; // must have this so we don't think they've said something after us as a result of the above hack
|
||
|
}
|
||
|
|
||
|
mem->inc = 199;
|
||
|
}
|
||
|
else // give them the watch
|
||
|
{
|
||
|
int index;
|
||
|
gitem_t *item;
|
||
|
|
||
|
// Lenny takes the watch
|
||
|
item = FindItem ("Watch");
|
||
|
index = ITEM_INDEX (item);
|
||
|
other->client->pers.inventory[ index ] = 0;
|
||
|
|
||
|
// other->episode_flags |= EP_SKIDROW_LENNY_TOOK_WATCH;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_LENNY_TOOK_WATCH;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_LENNY_TOOK_WATCH);
|
||
|
|
||
|
// Lenny gives player the key
|
||
|
Voice_Specific( self, other, lenny_table, 2 ); // here's the key
|
||
|
item = FindItem ("StoreRoomKey");
|
||
|
index = ITEM_INDEX (item);
|
||
|
other->client->pers.inventory[ index ]++;
|
||
|
// show icon and name on status bar
|
||
|
other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(item->icon);
|
||
|
other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+index;
|
||
|
other->client->pickup_msg_time = level.time + 5.5;
|
||
|
|
||
|
mem->inc = 0;
|
||
|
}
|
||
|
}
|
||
|
else // given them the watch, just chat
|
||
|
{
|
||
|
if (!mem->inc)
|
||
|
{
|
||
|
Voice_Specific( self, other, lenny_table, 14 );
|
||
|
mem->inc = 1;
|
||
|
}
|
||
|
else if (mem->inc == 1)
|
||
|
{ // thanks again
|
||
|
Voice_Random( self, other, &lenny_table[14], 2 );
|
||
|
mem->inc = 2;
|
||
|
}
|
||
|
else if (mem->inc == 2)
|
||
|
{ // you'd better leave now
|
||
|
Voice_Specific( self, other, lenny_table, 13 );
|
||
|
self->last_talk_time += 5; // this is a long one, give us more time to say it all
|
||
|
mem->inc = 3;
|
||
|
}
|
||
|
else // random stuff
|
||
|
{
|
||
|
Voice_Random( self, other, &lenny_table[10], 3 );
|
||
|
if (mem->inc++ > 4)
|
||
|
mem->inc = 1; /// thank them again
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
mem->response = Resp_Lenny;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// if we've cussed him, act hostile back
|
||
|
else if (other->response_ent == self && other->last_response == resp_no)
|
||
|
{
|
||
|
Voice_Random( self, other, &lenny_table[17], 3 );
|
||
|
other->response_ent = NULL; // get over it
|
||
|
}
|
||
|
|
||
|
// talked to them yet?
|
||
|
else if (other->client->pers.episode_flags & EP_TALKED_TO_LENNY)
|
||
|
{
|
||
|
// random chat, we've already asked them about Lamont
|
||
|
|
||
|
if (self->last_talk_time < (level.time - 15)) // haven't spoken for a while, they must have left and come back
|
||
|
{
|
||
|
Voice_Random( self, other, &lenny_table[22], 3 );
|
||
|
}
|
||
|
else if (mem->inc > 4)
|
||
|
{ // been here too long
|
||
|
Voice_Specific( self, other, lenny_table, 13 );
|
||
|
self->last_talk_time += 3; // this is a long one, give us more time to say it all
|
||
|
mem->inc = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random( self, other, &lenny_table[4], 9 );
|
||
|
mem->inc++;
|
||
|
}
|
||
|
|
||
|
mem->response = Resp_Lenny;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// first greeting
|
||
|
else
|
||
|
{
|
||
|
if (mem->inc == 0)
|
||
|
{ // hey you're that dude
|
||
|
Voice_Specific( self, other, lenny_table, 3 );
|
||
|
self->last_talk_time -= TALK_SELF_DELAY - 5;
|
||
|
other->last_talk_time = self->last_talk_time - 1; // must have this so we don't think they've said something after us as a result of the above hack
|
||
|
mem->inc++;
|
||
|
}
|
||
|
else if (mem->inc == 1)
|
||
|
{ // jesus
|
||
|
Voice_Specific( self, other, lenny_table, 17 );
|
||
|
self->last_talk_time -= TALK_SELF_DELAY - 2;
|
||
|
other->last_talk_time = self->last_talk_time - 1; // must have this so we don't think they've said something after us as a result of the above hack
|
||
|
mem->inc++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific( self, other, lenny_table, 4 ); // go kill lamont for me
|
||
|
|
||
|
// other->client->pers.episode_flags = other->episode_flags |= EP_TALKED_TO_LENNY;
|
||
|
self->last_talk_time -= TALK_SELF_DELAY - 3;
|
||
|
other->last_talk_time = self->last_talk_time - 1; // must have this so we don't think they've said something after us as a result of the above hack
|
||
|
|
||
|
mem->inc = 0;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_TALKED_TO_LENNY);
|
||
|
}
|
||
|
|
||
|
mem->response = Resp_Lenny;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//............................................................................
|
||
|
// LISA
|
||
|
// note to self:
|
||
|
// this will ensure that she keeps the same tone of voice
|
||
|
if ( self->name_index == NAME_LISA && other->client)/* && !other->client->pers.inventory[ITEM_INDEX(FindItem("Pistol"))])*/
|
||
|
{
|
||
|
int index;
|
||
|
// int rval;
|
||
|
edict_t *Igmo;
|
||
|
|
||
|
index = ITEM_INDEX (FindItem ("Pistol"));
|
||
|
|
||
|
Igmo = EP_GetCharacter( NAME_IGMO );
|
||
|
|
||
|
// check to see if the player has a pistol
|
||
|
if (!Igmo)
|
||
|
{
|
||
|
// gi.dprintf ("SOUND TODO: Shit... your one bad ass Dude!\n");
|
||
|
Voice_Specific (self, other, mona_specific, 13);
|
||
|
|
||
|
}
|
||
|
else if (other->client->pers.inventory [index])
|
||
|
{
|
||
|
Voice_Random (self, other, &lisa_specific[5], 3); // Ridah, NOTE! new method of playing specific sounds, without repeating one's self
|
||
|
}
|
||
|
else if (other->client->pers.episode_flags & EP_PAWNOMATIC_FIRST_TIME)
|
||
|
{
|
||
|
Voice_Random (self, other, &lisa_specific[2], 6);
|
||
|
}
|
||
|
else
|
||
|
Voice_Random(self, other, lisa_specific, 8);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
//............................................................................
|
||
|
// BETH
|
||
|
else if ( self->name_index == NAME_BETH && other->client)
|
||
|
{
|
||
|
if (other->client->pers.episode_flags & EP_SKIDROW_GOT_COIL)
|
||
|
{
|
||
|
Voice_Random (self, other, &beth_specific[4] , 3);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random(self, other, beth_specific, 6);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//............................................................................
|
||
|
// MONA
|
||
|
// JOSEPH 19-MAR-99
|
||
|
else if ( self->name_index == NAME_MONA && other->client)
|
||
|
{
|
||
|
edict_t *Lamont;
|
||
|
|
||
|
Lamont = EP_GetCharacter( NAME_LAMONT );
|
||
|
|
||
|
self->cast_info.aiflags &= ~AI_NO_TALK;
|
||
|
|
||
|
if (Lamont && !(other->episode_flags & EP_SKIDROW_MONA_FIRST_TIME))
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MONA_FIRST_TIME);
|
||
|
|
||
|
// If the player has killed Lamont
|
||
|
if ((!Lamont || Lamont->health <= 0))
|
||
|
{
|
||
|
if (!(other->client->pers.episode_flags & EP_TALKED_TO_LENNY) && rand()%2)
|
||
|
Voice_Random (self, other, &mona_specific[0], 4); // make sure they know about Lenny in the bar
|
||
|
else
|
||
|
Voice_Random (self, other, &mona_specific[13], 2); // you're one bad ass mofo
|
||
|
}
|
||
|
// If the player hasn't visited the bar
|
||
|
else if (!(other->client->pers.episode_flags & EP_BAR_FIRST_TIME))
|
||
|
{
|
||
|
Voice_Random (self, other, &mona_specific[0], 8);
|
||
|
}
|
||
|
// If the player hasn't talked to lenny
|
||
|
else if (!(other->client->pers.episode_flags & EP_TALKED_TO_LENNY))
|
||
|
{
|
||
|
Voice_Random (self, other, &mona_specific[10], 3);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random (self, other, &mona_specific[4], 6);
|
||
|
}
|
||
|
|
||
|
self->cast_info.aiflags |= AI_NO_TALK;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
|
||
|
//............................................................................
|
||
|
// MAGICJ
|
||
|
if ( (self->name_index == NAME_MAGICJ)
|
||
|
&& (other->client))
|
||
|
{
|
||
|
|
||
|
if (other->episode_flags & EP_SKIDROW_MAGICJ_GAVE_DOLLAR)
|
||
|
{
|
||
|
Voice_Random ( self, other, mj_random, 4);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_MAGICJ_ASKED_DOLLAR))
|
||
|
{
|
||
|
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 4 );
|
||
|
// other->episode_flags |= EP_SKIDROW_MAGICJ_ASKED_DOLLAR;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_MAGICJ_ASKED_DOLLAR;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MAGICJ_ASKED_DOLLAR);
|
||
|
|
||
|
mem->response = Resp_MagicJ_GotDollar;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// have they responded yet?
|
||
|
else if ( (other->response_ent == self)
|
||
|
&& (other->last_response_time > (level.time - 5)))
|
||
|
{
|
||
|
|
||
|
if (other->last_response == resp_yes)
|
||
|
{ // give the crow bar to the player
|
||
|
int index;
|
||
|
gitem_t *item;
|
||
|
|
||
|
Voice_Specific( self, other, specific, 7 );
|
||
|
item = FindItem ("Crowbar");
|
||
|
index = ITEM_INDEX (item);
|
||
|
other->client->pers.inventory[ index ]++;
|
||
|
// show icon and name on status bar
|
||
|
other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(item->icon);
|
||
|
other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+index;
|
||
|
other->client->pickup_msg_time = level.time + 5.5;
|
||
|
|
||
|
// other->episode_flags |= EP_SKIDROW_MAGICJ_GAVE_DOLLAR;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_MAGICJ_GAVE_DOLLAR;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MAGICJ_GAVE_DOLLAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 8 );
|
||
|
}
|
||
|
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
mem->response = NULL;
|
||
|
|
||
|
other->response_ent = NULL;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// randomly ask them about the iron bar
|
||
|
else if ( (specific[4].last_played < (level.time - 30))
|
||
|
&& (specific[9].last_played < (level.time - 40)))
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 9 );
|
||
|
|
||
|
if (mem = level.global_cast_memory[ self->character_index ][ other->character_index ])
|
||
|
mem->response = Resp_MagicJ_GotDollar;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
Voice_Random ( self, other, mj_random, 4);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
//............................................................................
|
||
|
// LEROY -> BETTY
|
||
|
if ( (self->name_index == NAME_LEROY)
|
||
|
&& (other->name_index == NAME_BETTY))
|
||
|
{
|
||
|
Voice_Random(self, self->cast_info.talk_ent, neutral_converse_to_female, NUM_NEUTRAL_CONVERSE_TO_FEMALE);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//............................................................................
|
||
|
// BUSTER -> JED (doors.bsp scripting test)
|
||
|
if ( (self->name_index == NAME_BUSTER)
|
||
|
&& (other->name_index == NAME_JED))
|
||
|
{
|
||
|
|
||
|
mem = level.global_cast_memory[self->character_index][other->character_index];
|
||
|
|
||
|
if (mem->inc++ > 2)
|
||
|
{ // time to bury them
|
||
|
Voice_Specific(self, other, profanity_level2, 14 );
|
||
|
AI_MakeEnemy( self, other, 0 );
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (mem->inc == 1)
|
||
|
Voice_Specific(self, other, profanity_level2, 7 );
|
||
|
else if (mem->inc == 2)
|
||
|
Voice_Specific(self, other, profanity_level2, 17 );
|
||
|
else if (mem->inc == 3)
|
||
|
Voice_Specific(self, other, profanity_level2, 11 );
|
||
|
|
||
|
// pretend he's going to respond soon, so we don't wait so long
|
||
|
other->last_talk_time = level.time + 2;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// JOSEPH 13-FEB-99
|
||
|
//............................................................................
|
||
|
// MOMO
|
||
|
if ( (self->name_index == NAME_MOMO)
|
||
|
&& (other->client))
|
||
|
{
|
||
|
return (ProcessMomo (self, other));
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
break;
|
||
|
|
||
|
case say_hostile:
|
||
|
|
||
|
if (self->name_index == NAME_ED && other->client)
|
||
|
{
|
||
|
Voice_Random (self, other, rummy, 4);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if ( self->name_index == NAME_BETH && other->client)
|
||
|
{
|
||
|
// Rafael: we need more negative sounds
|
||
|
if (rand()%100 > 75)
|
||
|
Voice_Random (self, other, &f_fightsounds[0],3);
|
||
|
else
|
||
|
Voice_Specific (self, other, beth_specific, 7);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//............................................................................
|
||
|
// MONA
|
||
|
// JOSEPH 19-MAR-99
|
||
|
if ( self->name_index == NAME_MONA && other->client)
|
||
|
{
|
||
|
{
|
||
|
edict_t *Lamont;
|
||
|
|
||
|
Lamont = EP_GetCharacter( NAME_LAMONT );
|
||
|
|
||
|
if (Lamont && !(other->episode_flags & EP_SKIDROW_MONA_FIRST_TIME))
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MONA_FIRST_TIME);
|
||
|
}
|
||
|
|
||
|
|
||
|
self->cast_info.aiflags &= ~AI_NO_TALK;
|
||
|
|
||
|
if (other->client->ps.stats[STAT_HUD_SELF_TALK] == TT_POSITIVE)
|
||
|
{
|
||
|
mem = level.global_cast_memory [self->character_index][other->character_index];
|
||
|
mem->flags &= ~MEMORY_ASSHOLE;
|
||
|
|
||
|
|
||
|
|
||
|
Voice_Random (self, other, &mona_specific[0], 8);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random (self, other, &mona_specific[15], 5);
|
||
|
}
|
||
|
|
||
|
self->cast_info.aiflags |= AI_NO_TALK;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
if ( (self->name_index == NAME_MAGICJ)
|
||
|
&& (other->client))
|
||
|
{
|
||
|
if (other->client->ps.stats[STAT_HUD_SELF_TALK] == TT_POSITIVE)
|
||
|
{
|
||
|
mem = level.global_cast_memory [self->character_index][other->character_index];
|
||
|
mem->flags &= ~MEMORY_ASSHOLE;
|
||
|
|
||
|
Voice_Random ( self, other, mj_random, 4);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
else
|
||
|
{
|
||
|
if ((rand()%10) < 4)
|
||
|
Voice_Specific (self, other, specific, 29);
|
||
|
else
|
||
|
Voice_Random ( self, other, &specific[23], 2);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( (self->name_index == NAME_RUMMY || self->name_index == NAME_NICK)
|
||
|
&& (other->client))
|
||
|
{
|
||
|
|
||
|
if (other->client->ps.stats[STAT_HUD_SELF_TALK] == TT_POSITIVE)
|
||
|
{
|
||
|
mem = level.global_cast_memory [self->character_index][other->character_index];
|
||
|
mem->flags &= ~MEMORY_ASSHOLE;
|
||
|
|
||
|
if (self->name_index == NAME_RUMMY)
|
||
|
Voice_Random (self, other, &rummy[12], 2);
|
||
|
else
|
||
|
{
|
||
|
if (!(other->episode_flags & EP_SKIDROW_NICK_TOLD_BIKE))
|
||
|
{
|
||
|
Voice_Specific (self, other, nick, 6);
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_TOLD_BIKE);
|
||
|
}
|
||
|
else
|
||
|
Voice_Random ( self, other, rummy, 3);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
else
|
||
|
{
|
||
|
|
||
|
if (self->name_index == NAME_RUMMY)
|
||
|
Voice_Random (self, other, &rummy[12], 2);
|
||
|
else
|
||
|
{
|
||
|
if (!(other->episode_flags & EP_SKIDROW_NICK_TOLD_BIKE))
|
||
|
{
|
||
|
Voice_Specific (self, other, nick, 6);
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_NICK_TOLD_BIKE);
|
||
|
}
|
||
|
else
|
||
|
Voice_Random ( self, other, rummy, 3);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// JOSEPH 13-FEB-99
|
||
|
if (self->name_index == NAME_MOMO && other->client)
|
||
|
{
|
||
|
return (ProcessMomo (self, other));
|
||
|
}
|
||
|
|
||
|
// END JOSEPH
|
||
|
|
||
|
if ( ((self->name_index == NAME_BETTY) || (self->name_index == NAME_LEROY))
|
||
|
&& other->client)
|
||
|
{
|
||
|
edict_t *betty;
|
||
|
betty = EP_GetCharacter (NAME_BETTY);
|
||
|
|
||
|
if (!betty || betty->health < 0)
|
||
|
return false;
|
||
|
|
||
|
self->last_talk_time = level.time;
|
||
|
|
||
|
{
|
||
|
edict_t *leroy;
|
||
|
leroy = EP_GetCharacter (NAME_LEROY);
|
||
|
|
||
|
if (leroy && leroy->health > 0)
|
||
|
{
|
||
|
// return true; // never speak to player if leroy is there
|
||
|
|
||
|
float time_offset;
|
||
|
|
||
|
time_offset = 0.0;
|
||
|
|
||
|
mem = level.global_cast_memory[ leroy->character_index ][ other->character_index ];
|
||
|
|
||
|
if (mem->flags & MEMORY_LASTWARNING && directly_infront(other, self)) // they're looking at her
|
||
|
{
|
||
|
Voice_Random ( leroy, self->cast_info.talk_ent, &specific[16], 2);
|
||
|
// Voice_Specific(leroy, self->cast_info.talk_ent, specific, 16 + rand()%2); // die
|
||
|
AI_MakeEnemy(leroy, self->cast_info.talk_ent, 0);
|
||
|
}
|
||
|
else if (mem->flags & MEMORY_UPSET)
|
||
|
{
|
||
|
mem->flags |= MEMORY_LASTWARNING;
|
||
|
|
||
|
if (!specific[15].last_played || specific[15].last_played > level.time)
|
||
|
Voice_Specific ( leroy, other, specific, 15); // step off
|
||
|
else
|
||
|
Voice_Random ( leroy, other, &specific[12], 3);
|
||
|
|
||
|
time_offset = 10.0;
|
||
|
}
|
||
|
else if (mem->flags & MEMORY_ASSHOLE)
|
||
|
{
|
||
|
Voice_Random ( leroy, other, &specific[12], 3);
|
||
|
|
||
|
mem->flags |= MEMORY_UPSET;
|
||
|
|
||
|
time_offset = 3.0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random ( leroy, other, &specific[12], 3);
|
||
|
|
||
|
mem->flags |= MEMORY_ASSHOLE;
|
||
|
}
|
||
|
|
||
|
last_client_talk = level.time + 3 + time_offset;
|
||
|
|
||
|
// Ridah, turn to face them, or make a gesture
|
||
|
if (!infront( leroy, other ))
|
||
|
{
|
||
|
leroy->cast_info.avoid( leroy, other, true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// make talking gesture if we're just standing around
|
||
|
if (leroy->cast_info.currentmove == leroy->cast_info.move_stand)
|
||
|
leroy->cast_info.talk(leroy);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Ridah, not used anymore
|
||
|
/*
|
||
|
if (self->name_index == NAME_LEROY && other->client)
|
||
|
{
|
||
|
{
|
||
|
edict_t *betty;
|
||
|
static int rnd;
|
||
|
float time_offset;
|
||
|
|
||
|
time_offset = 0.0;
|
||
|
|
||
|
mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
|
||
|
|
||
|
betty = EP_GetCharacter (NAME_BETTY);
|
||
|
|
||
|
if (betty && betty->health > 0)
|
||
|
{
|
||
|
if (VectorDistance( self->s.origin, betty->s.origin ) < 256)
|
||
|
{ // don't say anything just yet
|
||
|
// self->last_talk_time = level.time;
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// is not on the map anymore
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
break;
|
||
|
|
||
|
case say_flashlight:
|
||
|
|
||
|
// We put it in here so it only occurs if we aren't already angry at them
|
||
|
if (self->enemy != other)
|
||
|
{
|
||
|
cast_memory_t *mem, *premem;
|
||
|
|
||
|
// get the memory of this "other" character before we record the sighting
|
||
|
premem = level.global_cast_memory[self->character_index][other->character_index];
|
||
|
|
||
|
AI_RecordSighting(self, other, VectorDistance(self->s.origin, other->s.origin));
|
||
|
|
||
|
// get the post sighting memory
|
||
|
mem = level.global_cast_memory[self->character_index][other->character_index];
|
||
|
|
||
|
// if we recorded a new sighting (or hadn't seen them in a while), and they are hostile..
|
||
|
if ( (!premem || (premem->timestamp < (level.time - 10)))
|
||
|
&& (mem->flags & MEMORY_HOSTILE_ENEMY))
|
||
|
{
|
||
|
|
||
|
//gi.dprintf ("%s: there he is!\n", self->name); // Rafael: make sure you call the Voice routines, so they don't talk again for a bit
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
// Ridah, this is a mess, we should just scan for names, and go from there
|
||
|
/*
|
||
|
case say_alisthatyou:
|
||
|
AI_RecordSighting(self, other, VectorDistance(self->s.origin, other->s.origin));
|
||
|
gi.dprintf ("%s: Al is that you?\n", self->classname);
|
||
|
break;
|
||
|
case say_behindthebarrel: break;
|
||
|
case say_forabuck: break;
|
||
|
case say_talktobetty:
|
||
|
if (self->name_index == NAME_LEROY)
|
||
|
{
|
||
|
Voice_Random(self, self->cast_info.talk_ent, neutral_converse_to_female, NUM_NEUTRAL_CONVERSE_TO_FEMALE);
|
||
|
return true;
|
||
|
}
|
||
|
break;
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//............................................................................
|
||
|
// EP_Skidrow_ItemPickup
|
||
|
// Called whenever an item is picked up
|
||
|
|
||
|
void EP_Skidrow_ItemPickup ( edict_t *self, edict_t *other )
|
||
|
{
|
||
|
if (!Q_strcasecmp( self->classname, "item_coil" ))
|
||
|
{
|
||
|
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_GOT_COIL;
|
||
|
// other->episode_flags |= EP_SKIDROW_GOT_COIL;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_GOT_COIL);
|
||
|
}
|
||
|
|
||
|
// note to self
|
||
|
// for now they should just listen to the radio or wake up if they see the player
|
||
|
#if 0
|
||
|
edict_t /* *Al,*/ *Bernie, *Arnold, *radio ;
|
||
|
|
||
|
if (!Q_strcasecmp( self->classname, "item_coil" ))
|
||
|
{
|
||
|
|
||
|
other->episode_flags |= EP_SKIDROW_GOT_COIL;
|
||
|
|
||
|
//Al = EP_GetCharacter( NAME_AL );
|
||
|
Bernie = EP_GetCharacter( NAME_BERNIE );
|
||
|
|
||
|
if (/*Al &&*/ Bernie)
|
||
|
{
|
||
|
Bernie->cast_info.aiflags |= AI_GOAL_RUN; // So we run back to him
|
||
|
|
||
|
// send him to Bernie
|
||
|
|
||
|
//Al->goal_ent = Bernie; // this will make him walk to Bernie
|
||
|
// we then use the sight handler (above) to stop him
|
||
|
// when he gets close, and send them all to the 2nd door
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//Al = EP_GetCharacter( NAME_AL );
|
||
|
Bernie = EP_GetCharacter( NAME_BERNIE );
|
||
|
Arnold = EP_GetCharacter( NAME_ARNOLD );
|
||
|
|
||
|
//if (Al)
|
||
|
// AI_MakeEnemy(Al, other, 0);
|
||
|
if (Bernie)
|
||
|
AI_MakeEnemy(Bernie, other, 0);
|
||
|
if (Arnold)
|
||
|
AI_MakeEnemy(Arnold, other, 0);
|
||
|
|
||
|
// gi.dprintf ("CHEATER: AL, Arnold, and Bernie made hostile\n");
|
||
|
}
|
||
|
|
||
|
// kill the radio
|
||
|
radio = G_Find( NULL, FOFS(classname), "misc_skidrow_radio" );
|
||
|
if (!radio)
|
||
|
{
|
||
|
gi.dprintf( "EP_Skidrow_CastSight: Can't find radio to turn off!!\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
radio->think = NULL;
|
||
|
radio->nextthink = -1;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//............................................................................
|
||
|
// Special event-driven scripting. Usually called when a character reaches a
|
||
|
// path_corner_cast with the "scriptname" field set.
|
||
|
|
||
|
void EP_Skidrow_Script( edict_t *ent, char *scriptname )
|
||
|
{
|
||
|
edict_t *other;
|
||
|
|
||
|
//gi.dprintf( "Script '%s' called by %s\n", scriptname, ent->classname );
|
||
|
|
||
|
switch (ent->name_index)
|
||
|
{
|
||
|
|
||
|
//================================================================================================
|
||
|
// Test script using doors.bsp
|
||
|
case NAME_JED:
|
||
|
|
||
|
if (!strcmp( scriptname, "jed_script" ))
|
||
|
{
|
||
|
// Tell Jed to start evading Buster
|
||
|
ent->enemy = EP_GetCharacter( NAME_BUSTER );
|
||
|
AI_RecordSighting( ent, ent->enemy, VectorDistance( ent->s.origin, ent->enemy->s.origin ) );
|
||
|
ent->cast_info.currentmove = ent->cast_info.move_evade;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case NAME_BUSTER:
|
||
|
|
||
|
if (!strcmp( scriptname, "buster_script" ))
|
||
|
{
|
||
|
// Stand here looking at Jed
|
||
|
|
||
|
other = EP_GetCharacter( NAME_JED );
|
||
|
|
||
|
AI_RecordSighting( ent, other, VectorDistance( ent->s.origin, other->s.origin ) );
|
||
|
ent->cast_info.avoid( ent, other, true );
|
||
|
ent->cast_info.talk_ent = other;
|
||
|
|
||
|
|
||
|
// find our mates and tell them to look at Jed also, but don't talk
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i=0; i<level.num_characters; i++)
|
||
|
{
|
||
|
if (!level.characters[i])
|
||
|
continue;
|
||
|
|
||
|
if ( (level.characters[i] != ent)
|
||
|
&& (level.characters[i]->cast_group == ent->cast_group)
|
||
|
&& (VectorDistance( level.characters[i]->s.origin, ent->s.origin ) < 256))
|
||
|
{
|
||
|
AI_RecordSighting( level.characters[i], other, VectorDistance( level.characters[i]->s.origin, other->s.origin ) );
|
||
|
level.global_cast_memory[level.characters[i]->character_index][other->character_index]->flags |= MEMORY_NO_TALK;
|
||
|
|
||
|
level.characters[i]->cast_info.talk_ent = other;
|
||
|
|
||
|
level.characters[i]->cast_info.avoid( level.characters[i], other, true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
#define SR1_INTRO 1
|
||
|
|
||
|
#if SR1_INTRO // out for demo
|
||
|
//================================================================================================
|
||
|
// SR1 intro
|
||
|
|
||
|
case NAME_TOUGHGUY1:
|
||
|
|
||
|
if (!strcmp( scriptname, "intro_script1" ))
|
||
|
{ // say something, do talking motion
|
||
|
ent->last_talk_time = level.time + 2;
|
||
|
ent->cast_info.talk( ent );
|
||
|
|
||
|
ent->cast_info.pausetime = level.time + 7;
|
||
|
}
|
||
|
|
||
|
else if (!strcmp( scriptname, "intro_script2" ))
|
||
|
{ // tell the other guy to come with us
|
||
|
|
||
|
ent->yaw_speed = 40;
|
||
|
|
||
|
other = EP_GetCharacter( NAME_TOUGHGUY2 );
|
||
|
|
||
|
other->last_talk_time = level.time + 2;
|
||
|
other->cast_info.talk( ent );
|
||
|
|
||
|
other->yaw_speed = 40;
|
||
|
|
||
|
other->leader = ent;
|
||
|
// ent->cast_info.aiflags |= AI_GOALENT_MANUAL_CLEAR;
|
||
|
other->cast_info.pausetime = level.time + 2;
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
if (!strcmp( scriptname, "intro_player_script1" ))
|
||
|
{ // go into death frame
|
||
|
static mframe_t frames[] = {
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
NULL, 0, NULL,
|
||
|
};
|
||
|
static mmove_t move = {725, 755, frames, NULL};
|
||
|
|
||
|
other = EP_GetCharacter( NAME_INTROGUY1 );
|
||
|
|
||
|
other->yaw_speed = 5;
|
||
|
|
||
|
other->s.frame = move.firstframe;
|
||
|
other->cast_info.currentmove = &move;
|
||
|
|
||
|
other->s.model_parts[PART_GUN].invisible_objects = 0xFF;
|
||
|
|
||
|
if (!(cl_parental_lock->value && !cl_parental_override->value))
|
||
|
{
|
||
|
// set pain skins
|
||
|
other->s.model_parts[PART_HEAD].skinnum[0] = other->s.model_parts[PART_HEAD].baseskin + 1;
|
||
|
other->s.model_parts[PART_BODY].skinnum[0] = other->s.model_parts[PART_BODY].baseskin + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (!strcmp( scriptname, "intro_camera3" ))
|
||
|
{
|
||
|
void intro_player_standup( edict_t *self );
|
||
|
|
||
|
edict_t *thinker;
|
||
|
|
||
|
thinker = G_Spawn();
|
||
|
thinker->nextthink = level.time + 0.5;
|
||
|
thinker->think = intro_player_standup;
|
||
|
}
|
||
|
|
||
|
else if (!strcmp( scriptname, "intro_player_script1a" ))
|
||
|
{
|
||
|
// delete the tough guys
|
||
|
other = EP_GetCharacter( NAME_TOUGHGUY1 );
|
||
|
G_FreeEdict( other );
|
||
|
other = EP_GetCharacter( NAME_TOUGHGUY2 );
|
||
|
G_FreeEdict( other );
|
||
|
|
||
|
}
|
||
|
|
||
|
else if (!strcmp( scriptname, "intro_player_script2" ))
|
||
|
{ // we're at the corner, crouch down and grab the pipe
|
||
|
void intro_player_pickup_pipe( edict_t *self );
|
||
|
|
||
|
static mframe_t frames[] =
|
||
|
{
|
||
|
NULL, 0.000, NULL, // frame 0
|
||
|
NULL, 0.000, NULL, // frame 1
|
||
|
NULL, 0.000, NULL, // frame 2
|
||
|
NULL, 0.000, NULL, // frame 3
|
||
|
};
|
||
|
static mmove_t move = {570, 573, frames, intro_player_pickup_pipe};
|
||
|
|
||
|
ent->yaw_speed = 40;
|
||
|
|
||
|
// crouch down
|
||
|
ent->cast_info.currentmove = &move;
|
||
|
ent->s.frame = ent->cast_info.currentmove->firstframe;
|
||
|
ent->maxs[2] = DUCKING_MAX_Z;
|
||
|
|
||
|
|
||
|
// release the player from the camera
|
||
|
other = NULL;
|
||
|
while (other = G_Find( other, FOFS(classname), "misc_cutscene_trigger" ))
|
||
|
{
|
||
|
if (other->nextthink >= level.time && other->think)
|
||
|
{
|
||
|
other->wait = 2/FRAMETIME;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (!strcmp( scriptname, "intro_end" ))
|
||
|
{ // end of intro
|
||
|
|
||
|
other = EP_GetCharacter( NAME_INTROGUY1 );
|
||
|
G_FreeEdict( other );
|
||
|
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// Alarm
|
||
|
if (!strcmp( scriptname, "alarm" ))
|
||
|
{
|
||
|
// We need some assistance!
|
||
|
|
||
|
edict_t *marker;
|
||
|
|
||
|
// find the 2nd door ambush marker, tell all 3 guys to move to it
|
||
|
marker = G_Find( NULL, FOFS(classname), "misc_skidrow_ambush" );
|
||
|
if (!marker)
|
||
|
{
|
||
|
gi.dprintf( "EP_Skidrow_Script: Can't find ambush marker!!\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
edict_t *plyr;
|
||
|
|
||
|
if (plyr = EP_GetCharacter( NAME_BERNIE ))
|
||
|
{
|
||
|
plyr->goal_ent = plyr->start_ent = marker;
|
||
|
plyr->guard_ent = NULL;
|
||
|
plyr->target = NULL; // stop guarding the radio area/patrolling
|
||
|
}
|
||
|
|
||
|
// if (plyr = EP_GetCharacter( NAME_AL ))
|
||
|
// plyr->goal_ent = marker;
|
||
|
|
||
|
if (plyr = EP_GetCharacter( NAME_ARNOLD ))
|
||
|
{
|
||
|
plyr->goal_ent = marker;
|
||
|
plyr->guard_ent = NULL;
|
||
|
plyr->target = NULL; // stop guarding the radio area/patrolling
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// kill the radio
|
||
|
marker = G_Find( NULL, FOFS(classname), "misc_skidrow_radio" );
|
||
|
if (marker)
|
||
|
{
|
||
|
G_FreeEdict( marker );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||
|
#if SR1_INTRO // out for demo
|
||
|
|
||
|
void intro_player_standup( edict_t *self )
|
||
|
{ // stand up
|
||
|
edict_t *trav, *other;
|
||
|
|
||
|
trav = G_Find( NULL, FOFS(targetname), "intro_player_corner1a" );
|
||
|
|
||
|
other = EP_GetCharacter( NAME_INTROGUY1 );
|
||
|
|
||
|
other->cast_info.currentmove = other->cast_info.move_stand_up;
|
||
|
other->s.frame = other->cast_info.currentmove->firstframe;
|
||
|
other->maxs[2] = other->cast_info.standing_max_z;
|
||
|
|
||
|
other->last_talk_time = level.time; // make talking jesture when standing
|
||
|
|
||
|
// head for the corner in a few seconds
|
||
|
other->goal_ent = trav;
|
||
|
other->cast_info.goal_ent_pausetime = level.time + 2.5; // pause for a bit
|
||
|
|
||
|
// other->maxs[2] = DUCKING_MAX_Z;
|
||
|
}
|
||
|
|
||
|
void intro_player_turnaround( edict_t *self )
|
||
|
{
|
||
|
edict_t *other;
|
||
|
|
||
|
//self->owner->cast_info.currentmove = self->owner->cast_info.move_stand_up;
|
||
|
//self->owner->maxs[2] = self->owner->cast_info.standing_max_z;
|
||
|
|
||
|
// turn to face alley
|
||
|
other = NULL;
|
||
|
while (other = G_Find( other, FOFS(targetname), "intro_corner1" ))
|
||
|
{
|
||
|
// if (VectorDistance(self->owner->s.origin, other->s.origin) < 384)
|
||
|
{
|
||
|
self->owner->goal_ent = other;
|
||
|
// self->owner->cast_info.goal_ent_pausetime = level.time + 0.5;
|
||
|
self->owner->goal_ent->cast_info.aiflags |= AI_GOALENT_MANUAL_CLEAR;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
G_FreeEdict( self );
|
||
|
}
|
||
|
|
||
|
void intro_player_pickup_pipe( edict_t *self )
|
||
|
{
|
||
|
edict_t *think;
|
||
|
|
||
|
// show the pipe
|
||
|
self->s.model_parts[PART_GUN].invisible_objects = 0x0;
|
||
|
|
||
|
// self->cast_info.currentmove = self->cast_info.move_crstand;
|
||
|
self->cast_info.currentmove = self->cast_info.move_stand_up;
|
||
|
self->maxs[2] = self->cast_info.standing_max_z;
|
||
|
|
||
|
think = G_Spawn();
|
||
|
think->nextthink = level.time + 0.7;
|
||
|
think->think = intro_player_turnaround;
|
||
|
think->owner = self;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
qboolean EP_Skidrow_ProcessMagicJ( edict_t *self, edict_t *other, cast_memory_t *mem )
|
||
|
{
|
||
|
if ( (other->client)
|
||
|
&& (!(other->client->pers.holsteredweapon))
|
||
|
&& (mem->flags & MEMORY_AFRAID )
|
||
|
&& (other->client->pers.weapon) )
|
||
|
{
|
||
|
float dist;
|
||
|
|
||
|
dist = VectorDistance( self->s.origin, other->s.origin );
|
||
|
|
||
|
// if running, don't say or do anything
|
||
|
if (self->cast_info.currentmove->frame->aifunc == ai_run)
|
||
|
return true;
|
||
|
|
||
|
|
||
|
if ( (dist < AI_NOT_HOLSTERED_RANGE_1)
|
||
|
&& !(mem->flags & MEMORY_HOSTILE_ENEMY))
|
||
|
|
||
|
{
|
||
|
|
||
|
#define MAXCHOICES 8
|
||
|
|
||
|
edict_t *ent = NULL;
|
||
|
int num_choices = 0;
|
||
|
edict_t *choice[MAXCHOICES];
|
||
|
int rval;
|
||
|
float dist[MAXCHOICES];
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
ent = G_Find (ent, FOFS(classname), "misc_skidrow_afraid");
|
||
|
if (!ent)
|
||
|
break;
|
||
|
if ((dist[num_choices] = VectorDistance( ent->s.origin, self->s.origin )) > 384)
|
||
|
choice[num_choices++] = ent;
|
||
|
if (num_choices == MAXCHOICES)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (!num_choices)
|
||
|
{
|
||
|
// gi.dprintf( "AI: can't find a misc_skidrow_afraid\n");
|
||
|
mem->flags &= ~MEMORY_AFRAID;
|
||
|
}
|
||
|
else if (self->groundentity)
|
||
|
{
|
||
|
|
||
|
// gi.dprintf( "AI: Going to misc_skidrow_afraid\n");
|
||
|
// rval = rand() % num_choices;
|
||
|
{
|
||
|
int i;
|
||
|
float olddist = 0;
|
||
|
|
||
|
for (i=0; i<num_choices; i++)
|
||
|
{
|
||
|
if (dist[i] > olddist)
|
||
|
{
|
||
|
rval = i;
|
||
|
olddist = dist[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(choice[rval]->cast_info.aiflags & AI_GOAL_RUN))
|
||
|
// gi.sound(ent, CHAN_VOICE, gi.soundindex("actors/skidrow/magicj/fuckthat.wav"), 1, ATTN_NORM, 0);
|
||
|
Voice_Specific( self, other, specific, 25 );
|
||
|
|
||
|
choice[rval]->cast_info.aiflags |= AI_GOAL_RUN;
|
||
|
self->cast_info.aiflags |= AI_RUN_LIKE_HELL;
|
||
|
|
||
|
self->goal_ent = choice[rval];
|
||
|
self->cast_info.aiflags |= AI_GOAL_IGNOREENEMY;
|
||
|
|
||
|
self->cast_info.currentmove = self->cast_info.move_run;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (dist < AI_NOT_HOLSTERED_RANGE_2)
|
||
|
{
|
||
|
#define TIME_TO_COMPLY_OR_I_RUN 5.0
|
||
|
|
||
|
if (!(mem->flags & MEMORY_HOSTILE_ENEMY))
|
||
|
{
|
||
|
if ( (level.time > mem->not_holstered_attack_time)
|
||
|
&& (level.time < (mem->not_holstered_attack_time+5)))
|
||
|
{
|
||
|
// gi.dprintf ("stay away I'll fuck you up\n");
|
||
|
|
||
|
if (!(self->cast_info.aiflags & AI_NO_TALK))
|
||
|
{
|
||
|
self->cast_info.aiflags |= AI_NO_TALK;
|
||
|
|
||
|
if (rand()%3 == 0)
|
||
|
Voice_Specific( self, other, specific, 23 ); // fuck you up
|
||
|
else //if (rand()%3 == 1)
|
||
|
Voice_Specific( self, other, specific, 24 ); // fuck that
|
||
|
// else
|
||
|
// Voice_Specific( self, other, specific, 25 ); // be back
|
||
|
}
|
||
|
|
||
|
// Ridah, not sure what this was for, but it causes behavoural problem
|
||
|
// if (self->groundentity)
|
||
|
// self->cast_info.currentmove = self->cast_info.move_avoid_walk;
|
||
|
|
||
|
if (ai_debug_memory->value)
|
||
|
{
|
||
|
gi.dprintf("AI_RecordSighting: is cowering!\n");
|
||
|
}
|
||
|
}
|
||
|
else if (level.time > mem->not_holstered_attack_time)
|
||
|
{
|
||
|
|
||
|
if (!(other->client->pers.weapon->ammo))
|
||
|
Voice_Specific( self, other, specific, 22 ); // put that pipe down
|
||
|
else
|
||
|
Voice_Random( self, other, m_backoff, NUM_BACKOFF );
|
||
|
|
||
|
// give them some "time to comply"
|
||
|
mem->not_holstered_attack_time = level.time + TIME_TO_COMPLY_OR_I_RUN;
|
||
|
|
||
|
if (ai_debug_memory->value)
|
||
|
{
|
||
|
gi.dprintf("AI_RecordSighting: i'm about to run in %d seconds\n", (int) TIME_TO_COMPLY_OR_I_RUN);
|
||
|
}
|
||
|
|
||
|
// if we're standing around, turn to face them
|
||
|
if ( (self->cast_info.currentmove->frame->aifunc == ai_stand)
|
||
|
&& (self->cast_info.move_avoid_walk && self->cast_info.move_avoid_crwalk))
|
||
|
{
|
||
|
self->cast_info.avoid( self, other, true );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// if we're standing around, turn to face them
|
||
|
if (self->cast_info.currentmove->frame->aifunc == ai_stand)
|
||
|
{
|
||
|
vec3_t vec;
|
||
|
|
||
|
VectorSubtract( other->s.origin, self->s.origin, vec );
|
||
|
VectorNormalize( vec );
|
||
|
self->ideal_yaw = vectoyaw( vec );
|
||
|
|
||
|
M_ChangeYaw( self );
|
||
|
}
|
||
|
|
||
|
// evade?
|
||
|
if (self->cast_info.currentmove->frame->aifunc == ai_stand && self->cast_info.move_stand_evade && (self->moral < MORAL_AGGRESSIVE))
|
||
|
{
|
||
|
self->cast_info.currentmove = self->cast_info.move_stand_evade;
|
||
|
self->last_stand_evade = level.time;
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
else if (dist < AI_NOT_HOLSTERED_RANGE_3)
|
||
|
{ // if walking, ignore, if running, turn to face them, ready for attack if they get within range
|
||
|
|
||
|
if (VectorLength( other->velocity ) > 210)
|
||
|
{ // running
|
||
|
|
||
|
// if we're standing around, turn to face them
|
||
|
if (self->cast_info.currentmove->frame->aifunc == ai_stand)
|
||
|
{
|
||
|
vec3_t vec;
|
||
|
|
||
|
VectorSubtract( other->s.origin, self->s.origin, vec );
|
||
|
VectorNormalize( vec );
|
||
|
self->ideal_yaw = vectoyaw( vec );
|
||
|
|
||
|
M_ChangeYaw( self );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||
|
//
|
||
|
// Special Skidrow entities
|
||
|
|
||
|
//................................................
|
||
|
// Radio
|
||
|
|
||
|
/*QUAKED misc_skidrow_radio (.5 .5 1) (-16 -16 -24) (16 16 48)
|
||
|
Bernie and the guys will listen to this. After the radio has stopped,
|
||
|
they'll discuss the game for some time.
|
||
|
|
||
|
"delay" time to wait between starting to listen to the radio
|
||
|
"wait" time spent listening to the radio each time
|
||
|
"speed" time spent discussing the game afterwards
|
||
|
*/
|
||
|
|
||
|
/*QUAKED misc_skidrow_radio_repeater (.5 .5 1) (-16 -16 -24) (16 16 48)
|
||
|
Use to tag the speaker inside the warehouse
|
||
|
*/
|
||
|
|
||
|
void EP_Radio_On_First_Time (edict_t *self);
|
||
|
|
||
|
void radio_snd_think (edict_t *self)
|
||
|
{
|
||
|
self->count++;
|
||
|
|
||
|
if (self->count == 1)
|
||
|
{
|
||
|
gi.sound ( self, CHAN_VOICE, gi.soundindex ("world/cheerup.wav"), 1, ATTN_NORM, 0);
|
||
|
self->nextthink = level.time + 1.0;
|
||
|
}
|
||
|
else if (self->count == 2 || self->count == 3)
|
||
|
{
|
||
|
gi.sound ( self, CHAN_VOICE, gi.soundindex ("world/cheerhigh.wav"), 1, ATTN_NORM, 0);
|
||
|
self->nextthink = level.time + 6.0;
|
||
|
}
|
||
|
else if (self->count == 4)
|
||
|
{
|
||
|
gi.sound ( self, CHAN_VOICE, gi.soundindex ("world/cheerdown.wav"), 1, ATTN_NORM, 0);
|
||
|
self->nextthink = level.time + 2.0;
|
||
|
}
|
||
|
else
|
||
|
self->think = G_FreeEdict;
|
||
|
}
|
||
|
|
||
|
void Skidrow_Radio_Sound (edict_t *self)
|
||
|
{
|
||
|
edict_t *radio_snd;
|
||
|
|
||
|
radio_snd = G_Spawn ();
|
||
|
radio_snd->think = radio_snd_think;
|
||
|
radio_snd->nextthink = level.time + 0.1;
|
||
|
radio_snd->count = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void radio_loop_think (edict_t *self)
|
||
|
{
|
||
|
gi.sound ( self, CHAN_VOICE, gi.soundindex ("world/cheerlow.wav"), 1, ATTN_NORM, 0);
|
||
|
self->nextthink = level.time + 1.0;
|
||
|
}
|
||
|
|
||
|
void Skidrow_Radio_Loop (edict_t *self)
|
||
|
{
|
||
|
edict_t *radio_loop;
|
||
|
|
||
|
radio_loop = G_Spawn ();
|
||
|
radio_loop->think = radio_loop_think;
|
||
|
radio_loop->nextthink = level.time + 1.0;
|
||
|
}
|
||
|
|
||
|
void EP_skidrow_radio_stop_discuss (edict_t *self)
|
||
|
{
|
||
|
// self->think = EP_skidrow_radio_on;
|
||
|
self->think = EP_Radio_On_First_Time;
|
||
|
|
||
|
self->nextthink = level.time + self->delay;
|
||
|
self->timestamp = self->nextthink + self->wait; // set the time to stop playing
|
||
|
}
|
||
|
|
||
|
void EP_skidrow_radio_off (edict_t *self)
|
||
|
{
|
||
|
edict_t *Bernie/*, *Al*/, *Arnold;
|
||
|
|
||
|
Bernie = EP_GetCharacter( NAME_BERNIE );
|
||
|
// Al = EP_GetCharacter( NAME_AL );
|
||
|
Arnold = EP_GetCharacter( NAME_ARNOLD );
|
||
|
|
||
|
// Ridah 5-8-99, modified this to prevent courtyard wierdness after touching reset
|
||
|
|
||
|
if (Bernie)
|
||
|
{
|
||
|
if (Bernie->goal_ent == self)
|
||
|
{
|
||
|
Bernie->goal_ent = NULL;
|
||
|
if (!Bernie->enemy)
|
||
|
Bernie->cast_info.pausetime = level.time + self->speed; // stick around for a bit
|
||
|
}
|
||
|
|
||
|
Bernie->cast_info.aiflags |= AI_TALK;
|
||
|
}
|
||
|
/*
|
||
|
if (Al && (Al->goal_ent == self))
|
||
|
{
|
||
|
Al->goal_ent = NULL;
|
||
|
|
||
|
if (!Al->enemy)
|
||
|
Al->cast_info.pausetime = level.time + self->speed; // stick around for a bit
|
||
|
|
||
|
Al->cast_info.aiflags |= AI_TALK;
|
||
|
}
|
||
|
*/
|
||
|
if (Arnold)
|
||
|
{
|
||
|
if (Arnold->goal_ent == self)
|
||
|
{
|
||
|
Arnold->goal_ent = NULL;
|
||
|
if (!Arnold->enemy)
|
||
|
Arnold->cast_info.pausetime = level.time + self->speed; // stick around for a bit
|
||
|
}
|
||
|
|
||
|
Arnold->cast_info.aiflags |= AI_TALK;
|
||
|
}
|
||
|
|
||
|
self->think = EP_skidrow_radio_stop_discuss;
|
||
|
self->nextthink = level.time + self->speed;
|
||
|
}
|
||
|
|
||
|
void EP_skidrow_radio_on (edict_t *self)
|
||
|
{
|
||
|
edict_t *Bernie/*, *Al*/, *Arnold;
|
||
|
|
||
|
Bernie = EP_GetCharacter( NAME_BERNIE );
|
||
|
// Al = EP_GetCharacter( NAME_AL );
|
||
|
Arnold = EP_GetCharacter( NAME_ARNOLD );
|
||
|
|
||
|
|
||
|
if ( (Bernie)
|
||
|
&& !Bernie->enemy
|
||
|
&& (!Bernie->goal_ent || (Bernie->goal_ent->touch == path_corner_cast_touch))
|
||
|
&& (VectorDistance( Bernie->s.origin, self->s.origin ) < 1024))
|
||
|
{
|
||
|
Bernie->goal_ent = self;
|
||
|
|
||
|
Bernie->cast_info.aiflags &= ~AI_TALK; // don't talk while at radio
|
||
|
|
||
|
// Ridah, 5-8-99, we shouldn't need this anymore
|
||
|
}
|
||
|
/*
|
||
|
if ( (Al)
|
||
|
&& !Al->enemy
|
||
|
&& (!Al->goal_ent || (Al->goal_ent->touch == path_corner_cast_touch))
|
||
|
&& (VectorDistance( Al->s.origin, self->s.origin ) < 1024))
|
||
|
{
|
||
|
Al->goal_ent = self;
|
||
|
|
||
|
Al->cast_info.aiflags &= ~AI_TALK; // don't talk while at radio
|
||
|
}
|
||
|
*/
|
||
|
if ( (Arnold)
|
||
|
&& !Arnold->enemy
|
||
|
&& (!Arnold->goal_ent || (Arnold->goal_ent->touch == path_corner_cast_touch))
|
||
|
&& (VectorDistance( Arnold->s.origin, self->s.origin ) < 1024))
|
||
|
{
|
||
|
Arnold->goal_ent = self;
|
||
|
|
||
|
Arnold->cast_info.aiflags &= ~AI_TALK; // don't talk while at radio
|
||
|
|
||
|
// Ridah, 5-8-99, we shouldn't need this anymore
|
||
|
}
|
||
|
|
||
|
if (level.time > self->timestamp)
|
||
|
{ // turn the radio off
|
||
|
self->think = EP_skidrow_radio_off;
|
||
|
self->nextthink = level.time + 0.1;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self->nextthink = level.time + 3;
|
||
|
/*
|
||
|
Skidrow_Radio_Sound (self);
|
||
|
|
||
|
{
|
||
|
edict_t *repeater;
|
||
|
|
||
|
repeater = G_Find ( self, FOFS(classname), "misc_skidrow_radio_repeater");
|
||
|
|
||
|
if (repeater)
|
||
|
Skidrow_Radio_Sound (repeater);
|
||
|
}
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
void EP_Radio_On_First_Time (edict_t *self)
|
||
|
{
|
||
|
Skidrow_Radio_Sound (self);
|
||
|
/*
|
||
|
{
|
||
|
edict_t *repeater;
|
||
|
|
||
|
repeater = G_Find ( self, FOFS(classname), "misc_skidrow_radio_repeater");
|
||
|
|
||
|
if (repeater)
|
||
|
Skidrow_Radio_Sound (repeater);
|
||
|
}
|
||
|
*/
|
||
|
EP_skidrow_radio_on (self);
|
||
|
|
||
|
self->think = EP_skidrow_radio_on;
|
||
|
}
|
||
|
|
||
|
void SP_misc_skidrow_radio_repeater (edict_t *self)
|
||
|
{
|
||
|
self->movetype = MOVETYPE_NONE;
|
||
|
self->solid = SOLID_NOT;
|
||
|
gi.linkentity (self);
|
||
|
}
|
||
|
|
||
|
void SP_misc_skidrow_radio (edict_t *self)
|
||
|
{
|
||
|
if (deathmatch->value)
|
||
|
{
|
||
|
G_FreeEdict(self);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self->movetype = MOVETYPE_NONE;
|
||
|
self->solid = SOLID_NOT;
|
||
|
VectorSet (self->mins, -16, -16, -24);
|
||
|
VectorSet (self->maxs, 16, 16, 48);
|
||
|
|
||
|
// self->think = EP_skidrow_radio_on;
|
||
|
self->think = EP_Radio_On_First_Time;
|
||
|
self->nextthink = level.time + self->delay;
|
||
|
self->timestamp = self->nextthink + self->wait; // set the time to stop playing
|
||
|
|
||
|
self->cast_info.aiflags |= AI_GOALENT_MANUAL_CLEAR; // don't clear it out when we get there
|
||
|
self->cast_info.aiflags |= AI_GOAL_RUN; // run to us
|
||
|
|
||
|
// just for testing we need a constant background sound for the radio
|
||
|
// self->s.sound = gi.soundindex ("world/baseball.wav");
|
||
|
|
||
|
AI_Ent_droptofloor( self );
|
||
|
|
||
|
Skidrow_Radio_Loop (self);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*QUAKED misc_skidrow_ambush (.5 .5 1) (-16 -16 -24) (16 16 48)
|
||
|
Used to set ambush location for the 3 guards when the
|
||
|
player goes into the 2nd door.
|
||
|
*/
|
||
|
|
||
|
void SP_misc_skidrow_ambush (edict_t *self)
|
||
|
{
|
||
|
if (deathmatch->value)
|
||
|
{
|
||
|
G_FreeEdict(self);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self->movetype = MOVETYPE_NONE;
|
||
|
self->solid = SOLID_NOT;
|
||
|
VectorSet (self->mins, -16, -16, -24);
|
||
|
VectorSet (self->maxs, 16, 16, 48);
|
||
|
|
||
|
AI_Ent_droptofloor( self );
|
||
|
}
|
||
|
|
||
|
//==========================================================================================
|
||
|
//
|
||
|
// RESPONSES
|
||
|
|
||
|
// JOSEPH 23-MAR-99
|
||
|
void Resp_Lenny (edict_t *self, edict_t *other, response_t response)
|
||
|
{
|
||
|
if (response == resp_yes)
|
||
|
{
|
||
|
Voice_Specific( self, other, player_answer, 1 );
|
||
|
//Voice_Random( self, other, m_response, NUM_RESPONSE );
|
||
|
Voice_Player_Specific (self, TT_POSITIVE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random( self, other, player_profanity_level1, NUM_PROFANITY_LEVEL1 );
|
||
|
Voice_Player_Specific(self, TT_NEGATIVE);
|
||
|
}
|
||
|
|
||
|
self->response_ent = other;
|
||
|
self->last_response_time = level.time;
|
||
|
self->last_response = response;
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
|
||
|
void Resp_MagicJ_GotDollar( edict_t *self, edict_t *other, response_t response )
|
||
|
{
|
||
|
|
||
|
if (response == resp_yes)
|
||
|
{
|
||
|
Voice_Player_Specific(self, TT_YES);
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_MAGICJ_GAVE_DOLLAR))
|
||
|
{
|
||
|
// have we really got a dollar to give?
|
||
|
if (self->client->pers.currentcash >= 1)
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 5 );
|
||
|
|
||
|
// give him the dollar
|
||
|
|
||
|
self->client->pers.currentcash -= 1;
|
||
|
other->currentcash += 1;
|
||
|
|
||
|
other->episode_flags |= EP_SKIDROW_MAGICJ_GAVE_DOLLAR;
|
||
|
|
||
|
// EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MAGICJ_GAVE_DOLLAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 6 );
|
||
|
// gi.cprintf( self, PRINT_HIGH, "You don't have a dollar to give.\n" );
|
||
|
|
||
|
response = resp_no;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (response == resp_no)
|
||
|
{
|
||
|
Voice_Specific( self, other, specific, 6 );
|
||
|
Voice_Player_Specific(self, TT_NO);
|
||
|
}
|
||
|
|
||
|
self->response_ent = other;
|
||
|
self->last_response_time = level.time;
|
||
|
self->last_response = response;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void Resp_Rummy_GotWine ( edict_t *self, edict_t *other, response_t response )
|
||
|
{
|
||
|
|
||
|
int index;
|
||
|
gitem_t *item;
|
||
|
|
||
|
item = FindItem ("Whiskey");
|
||
|
index = ITEM_INDEX (item);
|
||
|
|
||
|
if (response == resp_yes)
|
||
|
{
|
||
|
Voice_Player_Specific(self, TT_YES);
|
||
|
|
||
|
if (!(self->episode_flags & EP_SKIDROW_RUMMY_GAVE_WINE))
|
||
|
{
|
||
|
if (self->client->pers.inventory[index])
|
||
|
{
|
||
|
// gi.dprintf ("FIXME: heres your wine\n");
|
||
|
Voice_Specific( self, other, player_whiskey, 0 );
|
||
|
|
||
|
other->episode_flags |= EP_SKIDROW_RUMMY_GAVE_WINE;
|
||
|
|
||
|
// EP_Skidrow_Register_EPFLAG (self, EP_SKIDROW_RUMMY_GAVE_WINE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// gi.cprintf( self, PRINT_HIGH, "FIXME: You don't have any wine to give.\n" );
|
||
|
|
||
|
Voice_Specific( self, other, player_whiskey, 1 );
|
||
|
response = resp_no;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// gi.cprintf( self, PRINT_HIGH, "FIXME: You don't have any wine to give.\n" );
|
||
|
Voice_Specific( self, other, player_whiskey, 1 );
|
||
|
response = resp_no;
|
||
|
}
|
||
|
}
|
||
|
else if (response == resp_no)
|
||
|
{
|
||
|
//gi.cprintf( self, PRINT_HIGH, "FIXME: I aint go any drink to give.\n" );
|
||
|
Voice_Specific( self, other, player_whiskey, 1 );
|
||
|
Voice_Player_Specific(self, TT_NO);
|
||
|
}
|
||
|
|
||
|
// hack to get rummy to work
|
||
|
other->cast_info.talk_ent = self;
|
||
|
|
||
|
self->response_ent = other;
|
||
|
self->last_response_time = level.time;
|
||
|
self->last_response = response;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*QUAKED misc_skidrow_afraid (.5 .5 1) (-16 -16 -24) (16 16 48)
|
||
|
used by actors to pick location where it is safer to run away from the player
|
||
|
*/
|
||
|
|
||
|
void SP_misc_skidrow_afraid (edict_t *self)
|
||
|
{
|
||
|
if (deathmatch->value)
|
||
|
{
|
||
|
G_FreeEdict(self);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
self->movetype = MOVETYPE_NONE;
|
||
|
self->solid = SOLID_NOT;
|
||
|
VectorSet (self->mins, -16, -16, -24);
|
||
|
VectorSet (self->maxs, 16, 16, 48);
|
||
|
|
||
|
self->cast_info.aiflags |= AI_RUN_LIKE_HELL;
|
||
|
|
||
|
AI_Ent_droptofloor( self );
|
||
|
}
|
||
|
|
||
|
|
||
|
// Pull Alarm routines
|
||
|
|
||
|
void Pull_Alarm_Ring (edict_t *ent)
|
||
|
{
|
||
|
edict_t *Louie;
|
||
|
|
||
|
Louie = EP_GetCharacter( NAME_LOUIE );
|
||
|
|
||
|
if ( Louie && ent->owner == Louie )
|
||
|
{
|
||
|
{
|
||
|
edict_t *entity = NULL;
|
||
|
edict_t *alarm = NULL;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
entity = G_Find (NULL, FOFS(classname), "misc_alarm");
|
||
|
if (!entity)
|
||
|
break;
|
||
|
if (VectorDistance( entity->s.origin, Louie->s.origin ) < 64)
|
||
|
{
|
||
|
alarm = entity;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!alarm)
|
||
|
{
|
||
|
ent->nextthink = level.time + 0.1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Louie->cast_info.aiflags &= ~AI_GOAL_IGNOREENEMY;
|
||
|
// Louie->cast_info.aiflags &= ~AI_GOAL_PULL_ALARM;
|
||
|
alarm->use (alarm, Louie, Louie);
|
||
|
G_FreeEdict(ent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Pull_Alarm_Think (edict_t *ent)
|
||
|
{
|
||
|
edict_t *Louie;
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
Louie = EP_GetCharacter( NAME_LOUIE );
|
||
|
|
||
|
if ( Louie && ent->owner == Louie )
|
||
|
{
|
||
|
mem = level.global_cast_memory[ Louie->character_index ][ ent->enemy->character_index ];
|
||
|
Louie->goal_ent = ent;
|
||
|
ent->cast_info.aiflags |= AI_GOAL_RUN;
|
||
|
ent->nextthink = level.time + 0.1;
|
||
|
ent->think = Pull_Alarm_Ring;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// the user must be dead so free it up
|
||
|
G_FreeEdict (ent);
|
||
|
|
||
|
}
|
||
|
/*
|
||
|
edict_t *FindCastOrigin (edict_t *self)
|
||
|
{
|
||
|
edict_t *ent = NULL;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
ent = G_Find (ent, FOFS(classname), "cast_origin");
|
||
|
if (!ent)
|
||
|
break;
|
||
|
if (ent->owner != self)
|
||
|
continue;
|
||
|
else
|
||
|
return ent;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
*/
|
||
|
void EP_Skidrow_Reset( edict_t *self, edict_t *other )
|
||
|
{
|
||
|
extern void AI_CreateCharacterMemory(edict_t *src, edict_t *dest);
|
||
|
extern void AI_ReleaseCastMemory(edict_t *self, cast_memory_t *cast_memory);
|
||
|
|
||
|
edict_t *Arnold, *Bernie;
|
||
|
cast_memory_t *mem;
|
||
|
edict_t *Cast_Origin;
|
||
|
|
||
|
if (!(other->client))
|
||
|
return;
|
||
|
|
||
|
Arnold = EP_GetCharacter( NAME_ARNOLD );
|
||
|
Bernie = EP_GetCharacter( NAME_BERNIE );
|
||
|
|
||
|
if (other->client && (other->client->pers.episode_flags & EP_SKIDROW_GOT_COIL))
|
||
|
return;
|
||
|
|
||
|
// both are still alive
|
||
|
if (Arnold && Bernie)
|
||
|
{
|
||
|
|
||
|
// TBD:
|
||
|
// actors need to go back to their start location
|
||
|
if (Arnold && (mem = level.global_cast_memory[ Arnold->character_index ][ other->character_index ]))
|
||
|
{
|
||
|
|
||
|
// Ridah, 5-8-99, some modifications for courtyard problems..
|
||
|
|
||
|
if (mem->memory_type == MEMORY_TYPE_ENEMY)
|
||
|
{
|
||
|
AI_ReleaseCastMemory( Arnold, Arnold->cast_info.enemy_memory );
|
||
|
Arnold->cast_info.enemy_memory = NULL;
|
||
|
}
|
||
|
|
||
|
// Ridah, 5-8-99, make it so we don't even remember the player
|
||
|
// AI_CreateCharacterMemory (Arnold, other);
|
||
|
|
||
|
// Ridah, DEMO: if they're currently in Louie's office, just spawn them back at the start pos
|
||
|
if (ValidBoxAtLoc( Arnold->start_ent->s.origin, Arnold->mins, Arnold->maxs, Arnold, MASK_PLAYERSOLID ))
|
||
|
VectorCopy( Arnold->start_ent->s.origin, Arnold->s.origin );
|
||
|
else // just run back there
|
||
|
Arnold->start_ent->cast_info.aiflags |= AI_GOAL_RUN;
|
||
|
|
||
|
Arnold->enemy = NULL;
|
||
|
Cast_Origin = Arnold->start_ent;
|
||
|
|
||
|
Arnold->goal_ent = Cast_Origin;
|
||
|
Arnold->cast_info.currentmove = Arnold->cast_info.move_stand;
|
||
|
|
||
|
}
|
||
|
if (Bernie && (mem = level.global_cast_memory[ Bernie->character_index ][ other->character_index ]))
|
||
|
{
|
||
|
|
||
|
// Ridah, 5-8-99, some modifications for courtyard problems..
|
||
|
|
||
|
if (mem->memory_type == MEMORY_TYPE_ENEMY)
|
||
|
{
|
||
|
AI_ReleaseCastMemory( Bernie, Bernie->cast_info.enemy_memory );
|
||
|
Bernie->cast_info.enemy_memory = NULL;
|
||
|
}
|
||
|
|
||
|
// Ridah, 5-8-99, make it so we don't even remember the player
|
||
|
// AI_CreateCharacterMemory (Bernie, other);
|
||
|
|
||
|
// Ridah, DEMO: if they're currently in Louie's office, just spawn them back at the start pos
|
||
|
if (ValidBoxAtLoc( Bernie->start_ent->s.origin, Bernie->mins, Bernie->maxs, Bernie, MASK_PLAYERSOLID ))
|
||
|
VectorCopy( Bernie->start_ent->s.origin, Bernie->s.origin );
|
||
|
else // just run back there
|
||
|
Bernie->start_ent->cast_info.aiflags |= AI_GOAL_RUN;
|
||
|
|
||
|
Bernie->enemy = NULL;
|
||
|
Cast_Origin = Bernie->start_ent;
|
||
|
|
||
|
Bernie->goal_ent = Cast_Origin;
|
||
|
Bernie->cast_info.currentmove = Bernie->cast_info.move_stand;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// JOSEPH 17-MAR-99
|
||
|
int EP_skidrow_touch_motorcycle_that_needs_battery_to_start (edict_t *self, edict_t *trigger)
|
||
|
{
|
||
|
|
||
|
|
||
|
// If the don't have the battery, then we don't get to go
|
||
|
if (!(self->client->pers.inventory[ITEM_INDEX(FindItem("Battery"))]))
|
||
|
{
|
||
|
if (!(self->episode_flags & EP_SKIDROW_FOUND_BIKE))
|
||
|
{
|
||
|
gi.sound(self, CHAN_VOICE, gi.soundindex("scenaric/bikenobattery.wav"), 1, ATTN_NORM, 0);
|
||
|
EP_Skidrow_Register_EPFLAG (self, EP_SKIDROW_FOUND_BIKE);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// JOSEPH 5-JUN-99
|
||
|
self->client->pers.inventory[ITEM_INDEX(FindItem("Battery"))] = 0;
|
||
|
// END JOSEPH
|
||
|
|
||
|
// Trigger triggered
|
||
|
G_UseTargets (trigger, self);
|
||
|
|
||
|
// Delete old bike
|
||
|
{
|
||
|
edict_t *e;
|
||
|
int i;
|
||
|
|
||
|
for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
|
||
|
{
|
||
|
if ((e->classname) && (!strcmp(e->classname, "props_motorcycle")))
|
||
|
{
|
||
|
G_FreeEdict(e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// New bike
|
||
|
{
|
||
|
edict_t *moto = NULL;
|
||
|
extern void SP_props_motorcycle_run (edict_t *self);
|
||
|
|
||
|
moto = G_Spawn();
|
||
|
|
||
|
if (!moto)
|
||
|
return 1;
|
||
|
|
||
|
SP_props_motorcycle_run(moto);
|
||
|
}
|
||
|
|
||
|
// Do camera cut
|
||
|
|
||
|
// Delete trigger brush
|
||
|
return 1;
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
void Resp_Momo_GotMoney ( edict_t *self, edict_t *other, response_t response )
|
||
|
{
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
if (self->episode_flags & EP_SKIDROW_MOMO_TOOK_MONEY)
|
||
|
return;
|
||
|
|
||
|
mem = level.global_cast_memory[ other->character_index ][ self->character_index ];
|
||
|
|
||
|
if (response == resp_yes)
|
||
|
{
|
||
|
Voice_Player_Specific(self, TT_YES);
|
||
|
Voice_Random (self, other, player_money_yes, NUM_PLAYER_MONEY_YES); // yes
|
||
|
}
|
||
|
else if (response == resp_no)
|
||
|
{
|
||
|
Voice_Player_Specific (self, TT_NO);
|
||
|
Voice_Random (self, other, player_money_no, NUM_PLAYER_MONEY_NO); // no
|
||
|
}
|
||
|
|
||
|
self->response_ent = other;
|
||
|
self->last_response_time = level.time;
|
||
|
self->last_response = response;
|
||
|
}
|
||
|
|
||
|
|
||
|
// generic process for hostile or neutral momo
|
||
|
qboolean ProcessMomo (edict_t *self, edict_t *other)
|
||
|
{
|
||
|
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
mem = level.global_cast_memory[ self->character_index ][ other->character_index ];
|
||
|
|
||
|
if (mem->flags & MEMORY_LASTWARNING)
|
||
|
{
|
||
|
Voice_Random ( self, other, &momo_specific[13], 2); // get the fuck out of my foyer
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (other->episode_flags & EP_SKIDROW_MOMO_TOOK_MONEY)
|
||
|
{
|
||
|
// Ridah, 5-8-99, we've already taken their money, so say one of the following..
|
||
|
|
||
|
if (!(mem->flags & MEMORY_ASSHOLE))
|
||
|
Voice_Random ( self, other, &momo_specific[12], 2); // so what's it gonna be... in or out?
|
||
|
else // they've cussed us, don't act all happy to see them
|
||
|
Voice_Random ( self, other, &momo_specific[13], 2); // get the fuck out of my foyer
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_MOMO_FIRST_TIME))
|
||
|
{
|
||
|
Voice_Specific (self, other, momo_specific, 0); // welcome.wav
|
||
|
|
||
|
// mem->inc = 1;
|
||
|
|
||
|
// other->episode_flags = other->client->pers.episode_flags |= EP_SKIDROW_MOMO_ASKED_MONEY;
|
||
|
// mem->response = Resp_Momo_GotMoney;
|
||
|
|
||
|
|
||
|
// other->episode_flags = other->client->pers.episode_flags |= EP_SKIDROW_MOMO_FIRST_TIME;
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MOMO_FIRST_TIME);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Ridah, 5-8-99, I changed this so it clears this flag in EP_CastSight() if Momo sees you after not having seen you for a while
|
||
|
if (!(other->episode_flags & EP_SKIDROW_MOMO_ASKED_MONEY))
|
||
|
{
|
||
|
// note to Rafael: you can use "inc" for anything.. usually used to count events
|
||
|
if (!mem->inc)
|
||
|
{
|
||
|
if (!( mem->flags & MEMORY_ASSHOLE))
|
||
|
{
|
||
|
Voice_Random (self, other, &momo_specific[1], 3); // 10 dollar cover charge
|
||
|
mem->inc = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific (self, other, momo_specific, 5); // now it's 20 bucks!
|
||
|
mem->inc = 2;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Specific (self, other, momo_specific, 9); // your back
|
||
|
}
|
||
|
|
||
|
// other->episode_flags = other->client->pers.episode_flags |= EP_SKIDROW_MOMO_ASKED_MONEY;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MOMO_ASKED_MONEY);
|
||
|
|
||
|
mem->response = Resp_Momo_GotMoney;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// have they responded yet?
|
||
|
else if ( (other->response_ent == self)
|
||
|
&& (other->last_response_time > (level.time - 5)))
|
||
|
{
|
||
|
|
||
|
if (other->last_response == resp_yes)
|
||
|
{
|
||
|
edict_t *door = NULL;
|
||
|
int cost;
|
||
|
|
||
|
if ( mem->flags & MEMORY_ASSHOLE)
|
||
|
{
|
||
|
if (mem->inc < 3)
|
||
|
cost = 20;
|
||
|
else
|
||
|
cost = 30;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cost = 10;
|
||
|
}
|
||
|
|
||
|
// have we really have money to give?
|
||
|
if (other->client->pers.currentcash >= cost)
|
||
|
{
|
||
|
other->client->pers.currentcash -= cost;
|
||
|
self->currentcash += cost;
|
||
|
|
||
|
// other->episode_flags = other->client->pers.episode_flags |= EP_SKIDROW_MOMO_TOOK_MONEY;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MOMO_TOOK_MONEY);
|
||
|
|
||
|
// TBD: at this point need to have momo walk away to a path corner cast
|
||
|
|
||
|
Voice_Specific( self, other, &momo_specific[0], 10 ); // go on in
|
||
|
|
||
|
|
||
|
// JOSEPH 9-MAR-99
|
||
|
// in case there's more than one door
|
||
|
{ // unlock the door for player
|
||
|
// Find target door
|
||
|
edict_t *e;
|
||
|
int i;
|
||
|
|
||
|
for (i=1, e=g_edicts+i ; i < globals.num_edicts ; i++,e++)
|
||
|
{
|
||
|
if ((e->targetname) && (!strcmp(e->targetname, "bardoor_sr")))
|
||
|
{
|
||
|
// Unlock target door
|
||
|
if (e->key == -1)
|
||
|
{
|
||
|
e->key = 0;
|
||
|
e->targetname = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// other->episode_flags |= EP_SKIDROW_MOMO_TOOK_MONEY;
|
||
|
// other->client->pers.episode_flags |= EP_SKIDROW_MOMO_TOOK_MONEY;
|
||
|
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_MOMO_TOOK_MONEY);
|
||
|
}
|
||
|
// END JOSEPH
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// don't have money to give
|
||
|
Voice_Random( self, other, &momo_specific[7], 2 ); // see me later when you got the money
|
||
|
}
|
||
|
}
|
||
|
else // they said no
|
||
|
{
|
||
|
Voice_Random( self, other, &momo_specific[13], 3 );
|
||
|
}
|
||
|
|
||
|
other->last_response_time = 0; // so we don't process this response again
|
||
|
|
||
|
mem->response = NULL;
|
||
|
other->response_ent = NULL;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
|
||
|
if (mem->flags & MEMORY_ASSHOLE)
|
||
|
{
|
||
|
if (!(mem->flags & MEMORY_UPSET))
|
||
|
{
|
||
|
mem->flags |= MEMORY_UPSET;
|
||
|
|
||
|
if (mem->inc < 3)
|
||
|
{
|
||
|
Voice_Specific (self, other, momo_specific, 5);
|
||
|
}
|
||
|
else // 30 bucks for you now!
|
||
|
{
|
||
|
Voice_Specific (self, other, momo_specific, 6);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random (self, other, &momo_specific[12], 4);
|
||
|
|
||
|
// This needs to be here, or Momo will never take the money when mad
|
||
|
if (momo_specific[12].last_played == level.time)
|
||
|
{ // we just asked them if they wanna come in, so let them respond
|
||
|
mem->response = Resp_Momo_GotMoney;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Voice_Random (self, other, &momo_specific[12], 5);
|
||
|
|
||
|
if (momo_specific[12].last_played == level.time)
|
||
|
{ // we just asked them if they wanna come in, so let them respond
|
||
|
mem->response = Resp_Momo_GotMoney;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void EP_SkidrowFlags (edict_t *self)
|
||
|
{
|
||
|
if (self->name_index == NAME_MOMO)
|
||
|
{
|
||
|
self->cast_info.aiflags |= AI_IMMORTAL;
|
||
|
self->s.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1);
|
||
|
self->s.model_parts[PART_GUN2].invisible_objects = (1<<0 | 1<<1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*UAKED immortal_hostility (.5 .5 1) (-16 -16 -24) (16 16 48)
|
||
|
This is an entity that will let an immortal check for player
|
||
|
hostility and take corresponding actions
|
||
|
|
||
|
health = the distance to check for ei a health of 64 would have a 128 diameter
|
||
|
*/
|
||
|
|
||
|
#if 0
|
||
|
void immortal_hostile_think (edict_t *self)
|
||
|
{
|
||
|
edict_t *player;
|
||
|
vec3_t vec;
|
||
|
float dist;
|
||
|
|
||
|
player = &g_edicts[1];
|
||
|
|
||
|
if (player->client->gun_noise)
|
||
|
{
|
||
|
|
||
|
VectorSubtract (self->s.origin, player->s.origin, vec);
|
||
|
dist = VectorLength (vec);
|
||
|
|
||
|
if (dist < self->health)
|
||
|
{
|
||
|
edict_t *dude;
|
||
|
cast_memory_t *mem;
|
||
|
|
||
|
{
|
||
|
dude = G_PickTarget(self->target);
|
||
|
|
||
|
if (dude)
|
||
|
{
|
||
|
mem = level.global_cast_memory[ dude->character_index ][ player->character_index ];
|
||
|
|
||
|
mem->flags |= MEMORY_LASTWARNING;
|
||
|
// gi.dprintf ("%s heard the shot\n", dude->name);
|
||
|
}
|
||
|
else
|
||
|
gi.dprintf ("player made gun noise in my detect zone!\n");
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self->nextthink = level.time + 0.1;
|
||
|
}
|
||
|
|
||
|
void SP_immortal_hostility (edict_t *self)
|
||
|
{
|
||
|
|
||
|
self->movetype = MOVETYPE_NONE;
|
||
|
self->solid = SOLID_NOT;
|
||
|
VectorSet (self->mins, -16, -16, -24);
|
||
|
VectorSet (self->maxs, 16, 16, 48);
|
||
|
|
||
|
if (!(self->health))
|
||
|
{
|
||
|
gi.dprintf ("setting default radius of 128\n");
|
||
|
self->health = 128;
|
||
|
}
|
||
|
|
||
|
self->think = immortal_hostile_think;
|
||
|
self->nextthink = level.time + 0.1;
|
||
|
|
||
|
AI_Ent_droptofloor( self );
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*QUAKED ep_skidrow_flag (.5 .5 0) ?
|
||
|
marks where the player can no longer fire his gun
|
||
|
*/
|
||
|
|
||
|
void ep_skidrow_flag_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
|
||
|
{
|
||
|
|
||
|
if (!(other->client))
|
||
|
return;
|
||
|
|
||
|
if (!(other->episode_flags & EP_SKIDROW_RATS_FIND))
|
||
|
{
|
||
|
EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_RATS_FIND);
|
||
|
// EP_Skidrow_Register_EPFLAG (other, EP_SKIDROW_CUT_SCENE_TWO);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void SP_ep_skidrow_flag ( edict_t *ent )
|
||
|
{
|
||
|
if (deathmatch->value)
|
||
|
{
|
||
|
G_FreeEdict(ent);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ent->solid = SOLID_TRIGGER;
|
||
|
ent->touch = ep_skidrow_flag_touch;
|
||
|
|
||
|
ent->svflags |= SVF_NOCLIENT;
|
||
|
|
||
|
gi.setmodel (ent, ent->model);
|
||
|
gi.linkentity (ent);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Skidrow flags
|
||
|
#define EP_SKIDROW_MAGICJ_ASKED_DOLLAR 0x00000001 //1
|
||
|
#define EP_SKIDROW_BETH_GIVES_HINT 0x00000002 //2
|
||
|
#define EP_SKIDROW_AL_SAW_DEAD_LOUIE 0x00000004 //3
|
||
|
#define EP_PAWNOMATIC_FIRST_TIME 0x00000008 //4
|
||
|
#define EP_SKIDROW_GOT_COIL 0x00000010 //5
|
||
|
#define EP_SKIDROW_MAGICJ_GAVE_DOLLAR 0x00000020 //6
|
||
|
#define EP_SKIDROW_MOMO_ASKED_MONEY 0x00000040 //7
|
||
|
#define EP_SKIDROW_MOMO_TOOK_MONEY 0x00000080 //8
|
||
|
#define EP_SKIDROW_MOMO_FIRST_TIME 0x00000100 //9
|
||
|
#define EP_TALKED_TO_LENNY 0x00000200 //10
|
||
|
#define EP_SKIDROW_MOMO_GAVE_MONEY 0x00000800 //11
|
||
|
#define EP_BAR_FIRST_TIME 0x00001000 //12
|
||
|
#define EP_SKIDROW_LENNY_TOOK_WATCH 0x00002000 //13
|
||
|
#define EP_SKIDROW_JOSEPH_WARNING_1 0x00004000 //16
|
||
|
#define EP_SKIDROW_JOSEPH_WARNING_2 0x00080000 //15
|
||
|
#define EP_SKIDROW_JOSEPH_WARNING_3 0x00100000 //16
|
||
|
#define EP_SKIDROW_RUMMY_GAVE_WINE 0x00200000 //17
|
||
|
#define EP_SKIDROW_RUMMY_ASKED_WINE 0x00400000 //18
|
||
|
#define EP_SKIDROW_RATS_PISSED 0x00800000 //19
|
||
|
*/
|
||
|
#include "ep_log.h"
|
||
|
|
||
|
int the_log_page = 0;
|
||
|
|
||
|
void EP_Skidrow_Player_Log (edict_t *self, int page)
|
||
|
{
|
||
|
int len;
|
||
|
int i;
|
||
|
int cnt = 0;
|
||
|
int select = 0;
|
||
|
|
||
|
len = 0;
|
||
|
|
||
|
Com_sprintf (game.helpmessage1, sizeof(game.helpmessage1), "");
|
||
|
Com_sprintf (game.helpmessage2, sizeof(game.helpmessage2), "");
|
||
|
|
||
|
the_log_page += page;
|
||
|
|
||
|
if (the_log_page < 0)
|
||
|
the_log_page = 0;
|
||
|
else if (the_log_page >= NUM_SKIDROW_PLAYER_LOG)
|
||
|
the_log_page = 0;
|
||
|
|
||
|
for (i=1; i<NUM_SKIDROW_PLAYER_LOG; i++)
|
||
|
{
|
||
|
if (self->client->pers.episode_flags & ep_skidrow_player_log[i].ep_flag)
|
||
|
cnt++;
|
||
|
|
||
|
if (cnt == the_log_page)
|
||
|
{
|
||
|
select = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!page || !the_log_page)
|
||
|
for (i=0; i<NUM_SKIDROW_PLAYER_LOG; i++)
|
||
|
{
|
||
|
if (ep_skidrow_player_log[i].new_clue == true)
|
||
|
{
|
||
|
select = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (cnt == 0)
|
||
|
{
|
||
|
the_log_page = 0;
|
||
|
strcpy (game.helpmessage1, " ");
|
||
|
|
||
|
if (ep_skidrow_player_log[select].new_clue)
|
||
|
strcat (game.helpmessage1, "new entry");
|
||
|
|
||
|
strcpy (game.helpmessage2, ep_skidrow_player_log[0].ep_text);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (select == 0)
|
||
|
the_log_page = 0;
|
||
|
strcpy (game.helpmessage1, " ");
|
||
|
|
||
|
if (ep_skidrow_player_log[select].new_clue)
|
||
|
strcat (game.helpmessage1, "new entry");
|
||
|
|
||
|
strcat (game.helpmessage2, ep_skidrow_player_log[select].ep_text);
|
||
|
if (page)
|
||
|
gi.sound(self, CHAN_VOICE, gi.soundindex("world/pageturn.wav"), 1, ATTN_NONE, 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void EP_Skidrow_Register_EPFLAG (edict_t *self, int ep_flag)
|
||
|
{
|
||
|
if (self->client->pers.episode_flags & ep_flag)
|
||
|
return;
|
||
|
|
||
|
self->episode_flags = self->client->pers.episode_flags |= ep_flag;
|
||
|
|
||
|
EP_Flash_Newflag (self, ep_flag);
|
||
|
}
|
||
|
|
||
|
|
||
|
void EP_Skidrow_CheckMomo (edict_t *ent, cast_memory_t *mem)
|
||
|
{
|
||
|
if (ent->episode_flags & EP_SKIDROW_MOMO_ASKED_MONEY)
|
||
|
mem->inc++;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
qboolean EP_Skidrow_Flash_Newflag (edict_t *self, int ep_flag)
|
||
|
{
|
||
|
int i;
|
||
|
qboolean gotone = false;
|
||
|
|
||
|
for (i=0; i<NUM_SKIDROW_PLAYER_LOG; i++)
|
||
|
{
|
||
|
if (ep_skidrow_player_log[i].ep_flag == ep_flag)
|
||
|
{
|
||
|
ep_skidrow_player_log[i].new_clue = true;
|
||
|
gotone = true;
|
||
|
}
|
||
|
else
|
||
|
ep_skidrow_player_log[i].new_clue = false;
|
||
|
}
|
||
|
|
||
|
return (gotone);
|
||
|
}
|