//----------------------------------------------------------------------------- // // $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 ); }