sin-sdk/powerups.cpp
1999-11-02 00:00:00 +00:00

656 lines
14 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/powerups.cpp $
// $Revision:: 24 $
// $Author:: Aldie $
// $Date:: 3/24/99 4:30p $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/powerups.cpp $
//
// 24 3/24/99 4:30p Aldie
// tried to bullet proof certain crash bugs
//
// 23 11/13/98 2:36a Aldie
// Added a fixdeadbodies for mutagen
//
// 22 11/09/98 1:47a Aldie
// Change tesselate stuff for mutagen
//
// 21 11/08/98 5:12p Markd
// Added mutant hands to precache of mutagen as well
//
// 20 11/07/98 9:32p Markd
// pre-cached manumit_pl in mutagen constructor
//
// 19 10/22/98 2:44a Aldie
// Reduced POWERUP_TIME to 30
//
// 18 10/20/98 8:05p Aldie
// Made oxygen autopickup and use.
//
// 17 10/19/98 11:50p Aldie
// Added yellow dynamic light to adrenaline
//
// 16 10/19/98 12:05a Jimdose
// made all code use fast checks for inheritance (no text lookups when
// possible)
// isSubclassOf no longer requires ::_classinfo()
// moved ScubaGear from keys.cpp
//
// 15 10/16/98 10:53p Aldie
// Remove mutagen after using
//
// 14 10/13/98 2:29p Aldie
// Check for owners on Powedown
//
// 13 10/12/98 3:49p Aldie
// Oxygen requires scubagear
//
// 12 10/11/98 8:58p Aldie
// Moved savemodel and saveskin to sentient
//
// 11 10/11/98 12:03a Aldie
// Adrenaline effects
//
// 10 10/06/98 9:17p Aldie
// Fixed some bugs with models and skins
//
// 9 10/06/98 3:06p Aldie
// Fix adrenaline function
//
// 8 10/01/98 7:57p Aldie
// Consolidated the cprintf
//
// 7 9/28/98 4:17p Aldie
// Added oxygen powerup
//
// 6 9/26/98 4:45p Aldie
// Added mutant mode
//
// 5 9/25/98 2:59p Aldie
// Added medkit
//
// 4 9/05/98 12:12p Aldie
// Added checks to see if powerups were active
//
// 3 8/31/98 5:44p Aldie
// Added cloak
//
// 2 8/27/98 2:30p Aldie
// Adrenaline
//
// DESCRIPTION:
// Miscellaneous powerups
#include "powerups.h"
#include "specialfx.h"
#include "player.h"
#define POWERUP_TIME 30
CLASS_DECLARATION( InventoryItem, ScubaGear, "inventory_scubagear" )
ResponseDef ScubaGear::Responses[] =
{
{ NULL, NULL }
};
ScubaGear::ScubaGear
(
)
{
setModel( "scubagear.def" );
}
CLASS_DECLARATION( InventoryItem, Adrenaline, "powerup_adrenaline" );
Event EV_Adrenaline_Powerdown( "adrenaline_powerdown" );
ResponseDef Adrenaline::Responses[] =
{
{ &EV_Adrenaline_Powerdown, ( Response )Adrenaline::Powerdown },
{ NULL, NULL }
};
Adrenaline::Adrenaline
(
)
{
setModel( "adren.def" );
Set( 1 );
setRespawnTime( 180 + G_Random( 60 ) );
}
void Adrenaline::Powerdown
(
Event *ev
)
{
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
owner->flags &= ~FL_ADRENALINE;
owner->edict->s.renderfx &= ~RF_DLIGHT;
owner->edict->s.color_r = 0;
owner->edict->s.color_g = 0;
owner->edict->s.color_b = 0;
owner->edict->s.radius = 0;
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
}
void Adrenaline::Use
(
Event *ev
)
{
str realname;
Event *event;
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
if ( owner->PowerupActive() )
{
return;
}
// Make sure there is one available
assert( amount );
amount--;
if (amount <= 0)
{
owner->RemoveItem( this );
}
PostEvent( EV_Adrenaline_Powerdown, POWERUP_TIME );
owner->flags |= FL_ADRENALINE;
event = new Event( "poweruptimer" );
event->AddInteger( POWERUP_TIME );
event->AddInteger( P_ADRENALINE );
owner->edict->s.renderfx |= RF_DLIGHT;
owner->edict->s.color_r = 1;
owner->edict->s.color_g = 1;
owner->edict->s.color_b = 0;
owner->edict->s.radius = 120;
owner->ProcessEvent ( event );
realname = GetRandomAlias( "snd_activate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}
CLASS_DECLARATION( InventoryItem, Cloak, "powerups_cloak" );
Event EV_Cloak_Powerdown( "Cloak_powerdown" );
ResponseDef Cloak::Responses[] =
{
{ &EV_Cloak_Powerdown, ( Response )Cloak::Powerdown },
{ NULL, NULL }
};
Cloak::Cloak
(
)
{
setModel( "cloak.def" );
Set( 1 );
setRespawnTime( 180 + G_Random( 60 ) );
}
void Cloak::Powerdown
(
Event *ev
)
{
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
if ( owner->flags & FL_CLOAK )
{
str realname;
owner->flags &= ~FL_CLOAK;
realname = GetRandomAlias( "snd_deactivate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
owner->edict->s.renderfx &= ~RF_DLIGHT;
owner->edict->s.color_r = 0;
owner->edict->s.color_g = 0;
owner->edict->s.color_b = 0;
owner->edict->s.radius = 0;
}
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
}
void Cloak::Use
(
Event *ev
)
{
str realname;
Event *event;
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
if ( owner->PowerupActive() )
{
return;
}
// Make sure there is one available
assert( amount );
amount--;
if (amount <= 0)
{
owner->RemoveItem( this );
}
PostEvent( EV_Cloak_Powerdown, POWERUP_TIME );
owner->flags |= FL_CLOAK;
owner->edict->s.renderfx |= RF_DLIGHT;
owner->edict->s.color_r = 1;
owner->edict->s.color_g = 1;
owner->edict->s.color_b = 1;
owner->edict->s.radius = -120;
event = new Event( "poweruptimer" );
event->AddInteger( POWERUP_TIME );
event->AddInteger( P_CLOAK );
owner->ProcessEvent ( event );
realname = GetRandomAlias( "snd_activate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}
CLASS_DECLARATION( InventoryItem, Mutagen, "powerups_mutagen" );
Event EV_Mutagen_Powerdown( "mutagen_powerdown" );
ResponseDef Mutagen::Responses[] =
{
{ &EV_Mutagen_Powerdown, ( Response )Mutagen::Powerdown },
{ NULL, NULL }
};
Mutagen::Mutagen
(
)
{
modelIndex( "manumit_pl.def" );
modelIndex( "view_mutanthands.def" );
setModel( "u4vial.def" );
Set( 1 );
setRespawnTime( 180 + G_Random( 60 ) );
}
void Mutagen::Powerdown
(
Event *ev
)
{
str realname;
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
owner->flags &= ~FL_MUTANT;
realname = GetRandomAlias( "snd_deactivate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
if ( owner->isClient() )
{
int playernum = owner->edict-g_edicts-1;
owner->setModel( owner->savemodel );
owner->RandomAnimate( "idle", NULL );
strcpy( owner->client->pers.model, owner->savemodel.c_str() );
strcpy( owner->client->pers.skin, owner->saveskin.c_str() );
// combine name, skin and model into a configstring
gi.configstring (CS_PLAYERSKINS+playernum, va("%s\\%s\\%s",
owner->client->pers.netname,
owner->client->pers.model,
owner->client->pers.skin));
}
owner->takeWeapon( "MutantHands" );
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
}
void Mutagen::Use
(
Event *ev
)
{
str realname;
Event *event;
Weapon *mutanthands;
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
if ( owner->PowerupActive() )
{
return;
}
// Make sure there is one available
assert( amount );
amount--;
if (amount <= 0)
{
owner->RemoveItem( this );
}
PostEvent( EV_Mutagen_Powerdown, POWERUP_TIME );
owner->flags |= FL_MUTANT;
//Set the timer
event = new Event( "poweruptimer" );
event->AddInteger( POWERUP_TIME );
event->AddInteger( P_MUTAGEN );
owner->ProcessEvent ( event );
TesselateModel(owner,
1,
1000,
Vector( "0 0 1" ),
50,
0.1f,
owner->tess_thickness,
vec3_origin
);
owner->savemodel = COM_SkipPath(owner->model.c_str());
owner->saveskin = COM_SkipPath(owner->client->pers.skin);
owner->setModel( "manumit_pl.def" );
owner->RandomAnimate( "idle", NULL );
if ( owner->isClient() )
{
int playernum = owner->edict-g_edicts-1;
strcpy( owner->client->pers.model, "manumit_pl.def" );
strcpy( owner->client->pers.skin, "manu_base.tga" );
// combine name, skin and model into a configstring
gi.configstring (CS_PLAYERSKINS+playernum,
va("%s\\%s\\%s",
owner->client->pers.netname,
owner->client->pers.model,
owner->client->pers.skin)
);
FixDeadBodiesForPlayer( owner->edict );
}
// Give the mutanthands weapon. - Force it.
mutanthands = owner->giveWeapon( "MutantHands" );
owner->ForceChangeWeapon( mutanthands );
realname = GetRandomAlias( "snd_activate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}
/*****************************************************************************/
/*SINED misc_medkit (1.0 0.2 0.2)
Heals whoever uses it to their max health.
/*****************************************************************************/
CLASS_DECLARATION( Entity, Medkit, "misc_medkit" );
ResponseDef Medkit::Responses[] =
{
{ &EV_Use, ( Response )Medkit::Use },
{ NULL, NULL }
};
Medkit::Medkit
(
)
{
setSolidType( SOLID_BSP );
setMoveType( MOVETYPE_NONE );
showModel();
}
void Medkit::Use
(
Event *ev
)
{
Entity *other;
str realname;
other = ev->GetEntity( 1 );
if ( other && other->health < other->max_health )
{
other->health = other->max_health;
realname = GetRandomAlias( "snd_activate" );
if ( realname.length() )
other->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}
}
CLASS_DECLARATION( InventoryItem, Oxygen, "powerups_oxygen" );
Event EV_Oxygen_Powerdown( "oxygen_powerdown" );
ResponseDef Oxygen::Responses[] =
{
{ &EV_Oxygen_Powerdown, ( Response )Oxygen::Powerdown },
{ &EV_Item_Pickup, ( Response )Oxygen::Pickup },
{ NULL, NULL }
};
Oxygen::Oxygen
(
)
{
setModel( "oxygen.def" );
Set( 1 );
setRespawnTime( 180 + G_Random( 60 ) );
}
void Oxygen::Powerdown
(
Event *ev
)
{
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
if ( owner->flags & FL_OXYGEN )
{
str realname;
owner->flags &= ~FL_OXYGEN;
realname = GetRandomAlias( "snd_deactivate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
}
void Oxygen::Pickup
(
Event *ev
)
{
Entity *other;
Sentient *sen;
Item *item;
other = ev->GetEntity( 1 );
if ( !other )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
sen = ( Sentient * )other;
// Single player must have the scuba gear to use oxygen
if ( !deathmatch->value && !sen->FindItem( "ScubaGear" ) )
{
Item *item;
item = ( Item * )new ScubaGear;
item->CancelEventsOfType( EV_Item_DropToFloor );
item->CancelEventsOfType( EV_Remove );
item->ProcessPendingEvents();
gi.centerprintf( other->edict, "jcx yv 20 string \"You need this item to use Oxygen:\" jcx yv -20 icon %d", item->GetIconIndex() );
delete item;
return;
}
if ( !ItemPickup( sen ) )
return;
if ( sen->isSubclassOf( Player ) )
{
Player *player = ( Player * )sen;
player->GiveOxygen( 60 );
}
item = sen->FindItem( getClassname() );
if ( item )
{
CancelPendingEvents();
item->PostEvent( EV_Remove, 0 );
}
}
void Oxygen::Use
(
Event *ev
)
{
str realname;
Event *event;
if ( !owner )
{
CancelPendingEvents();
PostEvent( EV_Remove, 0 );
return;
}
// Single player must have the scuba gear to use oxygen
if ( !deathmatch->value && !owner->FindItem( "ScubaGear" ) )
{
Item *item;
item = ( Item * )new ScubaGear;
item->CancelEventsOfType( EV_Item_DropToFloor );
item->CancelEventsOfType( EV_Remove );
item->ProcessPendingEvents();
gi.centerprintf( owner->edict, "jcx yv 20 string \"You need this item to use Oxygen:\" jcx yv -20 icon %d", item->GetIconIndex() );
delete item;
return;
}
if ( owner->PowerupActive() )
{
return;
}
// Make sure there is one available
assert( amount );
amount--;
if (amount <= 0)
{
owner->RemoveItem( this );
}
PostEvent( EV_Oxygen_Powerdown, 60 );
owner->flags |= FL_OXYGEN;
event = new Event( "poweruptimer" );
event->AddInteger( 60 );
event->AddInteger( P_OXYGEN );
owner->ProcessEvent ( event );
realname = GetRandomAlias( "snd_activate" );
if ( realname.length() )
owner->sound( realname, 1, CHAN_ITEM, ATTN_NORM );
}