ef2-sdk/dlls/game/object.cpp

484 lines
9.4 KiB
C++
Raw Normal View History

2003-11-05 00:00:00 +00:00
//-----------------------------------------------------------------------------
//
// $Logfile:: /EF2/Code/DLLs/game/object.cpp $
// $Revision:: 9 $
// $Author:: Singlis $
// $Date:: 9/26/03 2:36p $
//
// 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.
//
//
// DESCRIPTION:
//
#include "_pch_cpp.h"
#include "object.h"
#include "sentient.h"
#include "misc.h"
#include "explosion.h"
#include "gibs.h"
#include "specialfx.h"
Event EV_Object_Setup
(
"_setup",
EV_CODEONLY,
NULL,
NULL,
"Sets up an object."
);
Event EV_Object_SetAnim
(
"anim",
EV_DEFAULT,
"s",
"animname",
"Sets up the object with the specified animname."
);
Event EV_Object_Shootable
(
"shootable",
EV_DEFAULT,
NULL,
NULL,
"Make the object shootable but not necessarily solid to the player."
);
CLASS_DECLARATION( Entity, Object, "object" )
{
{ &EV_Killed, &Object::Killed },
{ &EV_Object_Setup, &Object::Setup },
{ &EV_Object_SetAnim, &Object::SetAnim },
{ &EV_Object_Shootable, &Object::MakeShootable },
{ NULL, NULL }
};
Object::Object()
{
animate = new Animate( this );
if ( LoadingSavegame )
{
// Archive function will setup all necessary data
return;
}
//
// all objects default to not solid
//
setSolidType( SOLID_NOT );
health = 0;
takedamage = ( spawnflags & 2 ) ? DAMAGE_NO : DAMAGE_YES;
//
// we want the bounds of this model auto-rotated
//
flags |= FL_ROTATEDBOUNDS;
if ( !com_blood->integer )
{
flags &= ~FL_BLOOD;
flags &= ~FL_DIE_GIBS;
}
PostEvent( EV_Object_Setup, EV_POSTSPAWN );
}
void Object::SetAnim( Event *ev )
{
int animnum;
if ( ( ev->NumArgs() >= 1 ) && gi.IsModel( edict->s.modelindex ) )
{
animnum = gi.Anim_Random( edict->s.modelindex, ev->GetString( 1 ) );
if ( animnum >= 0 )
{
animate->NewAnim( animnum );
}
}
}
void Object::Setup( Event *ev )
{
if ( !health )
{
health = ( maxs - mins ).length();
max_health = health;
}
}
void Object::MakeShootable( Event *ev )
{
setContents( CONTENTS_SHOOTABLE_ONLY );
link();
}
void Object::Killed(Event *ev)
{
Entity * ent;
Entity * attacker;
Vector dir;
Event * event;
const char * name;
takedamage = DAMAGE_NO;
setSolidType( SOLID_NOT );
hideModel();
attacker = ev->GetEntity( 1 );
if (flags & FL_DIE_EXPLODE)
{
CreateExplosion( origin, 50.0f, this, this, this );
}
if (flags & FL_DIE_GIBS)
{
setSolidType( SOLID_NOT );
hideModel();
CreateGibs( this, -150.0f, edict->s.scale, 3 );
}
//
// kill the killtargets
//
name = KillTarget();
if ( name && strcmp( name, "" ) )
{
ent = NULL;
do
{
ent = G_FindTarget( ent, name );
if ( !ent )
{
break;
}
ent->PostEvent( EV_Remove, 0.0f );
}
while ( 1 );
}
//
// fire targets
//
name = Target();
if ( name && strcmp( name, "" ) )
{
ent = NULL;
do
{
ent = G_FindTarget( ent, name );
if ( !ent )
{
break;
}
event = new Event( EV_Activate );
event->AddEntity( attacker );
ent->ProcessEvent( event );
}
while ( 1 );
}
PostEvent( EV_Remove, 0.0f );
}
/*****************************************************************************/
/*QUAKED func_throwobject (0 0.25 0.5) (-16 -16 0) (16 16 32)
This is an object you can pickup and throw at people
******************************************************************************/
Event EV_ThrowObject_Pickup
(
"pickup",
EV_DEFAULT,
"es",
"entity tag_name",
"Picks up this throw object and attaches it to the entity."
);
Event EV_ThrowObject_Throw
(
"throw",
EV_DEFAULT,
"efeF",
"owner speed targetent grav",
"Throw this throw object."
);
Event EV_ThrowObject_PickupOffset
(
"pickupoffset",
EV_DEFAULT,
"v",
"pickup_offset",
"Sets the pickup_offset."
);
Event EV_ThrowObject_ThrowSound
(
"throwsound",
EV_DEFAULT,
"s",
"throw_sound",
"Sets the sound to play when object is thrown."
);
CLASS_DECLARATION( Object, ThrowObject, "func_throwobject" )
{
{ &EV_Touch, &ThrowObject::Touch },
{ &EV_ThrowObject_Pickup, &ThrowObject::Pickup },
{ &EV_ThrowObject_Throw, &ThrowObject::Throw },
{ &EV_ThrowObject_PickupOffset, &ThrowObject::PickupOffset },
{ &EV_ThrowObject_ThrowSound, &ThrowObject::ThrowSound },
{ NULL, NULL }
};
ThrowObject::ThrowObject()
{
if ( LoadingSavegame )
{
// Archive function will setup all necessary data
return;
}
pickup_offset = vec_zero;
damage = 0;
hurt_target = false;
owner = NULL;
}
void ThrowObject::PickupOffset( Event *ev )
{
pickup_offset = edict->s.scale * ev->GetVector( 1 );
}
void ThrowObject::ThrowSound( Event *ev )
{
throw_sound = ev->GetString( 1 );
}
void ThrowObject::Touch( Event *ev )
{
Entity *other;
if ( movetype != MOVETYPE_BOUNCE )
{
return;
}
other = ev->GetEntity( 1 );
assert( other );
if ( other->isSubclassOf( Teleporter ) )
{
return;
}
if ( other->entnum == owner )
{
return;
}
if ( throw_sound.length() )
{
StopLoopSound();
}
if ( other->takedamage && !hurt_target )
{
// other->Damage( this, G_GetEntity( owner ), size.length() * velocity.length() / 400, origin, velocity,
// level.impact_trace.plane.normal, 32, 0, MOD_THROWNOBJECT );
other->Damage( this, G_GetEntity( owner ), damage, origin, velocity,
level.impact_trace.plane.normal, 32, 0, MOD_THROWNOBJECT );
hurt_target = true;
}
//Damage( this, this, max_health, origin, velocity, level.impact_trace.plane.normal, 32, 0, MOD_THROWNOBJECT );
Damage( this, this, 0.0f, origin, velocity, level.impact_trace.plane.normal, 32, 0, MOD_THROWNOBJECT );
}
void ThrowObject::Throw( const Entity *owner, float speed, const Sentient *targetent, float gravity, float throw_damage )
{
float traveltime;
float vertical_speed;
Vector target;
Vector dir;
Vector xydir;
Event *e;
e = new Event( EV_Detach );
ProcessEvent( e );
this->owner = owner->entnum;
edict->ownerNum = owner->entnum;
damage = throw_damage;
target = targetent->origin;
target.z += targetent->viewheight;
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
edict->clipmask = MASK_PROJECTILE;
dir = target - origin;
xydir = dir;
xydir.z = 0;
traveltime = xydir.length() / speed;
vertical_speed = ( dir.z / traveltime ) + ( 0.5f * gravity * sv_currentGravity->value * traveltime );
xydir.normalize();
// setup ambient flying sound
if ( throw_sound.length() )
{
LoopSound( throw_sound.c_str() );
}
velocity = speed * xydir;
velocity.z = vertical_speed;
angles = velocity.toAngles();
setAngles( angles );
avelocity.x = crandom() * 200.0f;
avelocity.y = crandom() * 200.0f;
takedamage = DAMAGE_YES;
}
void ThrowObject::Throw( Event *ev )
{
Entity *owner;
Sentient *targetent;
float speed;
float grav;
float throw_damage;
owner = ev->GetEntity( 1 );
assert( owner );
if ( !owner )
{
return;
}
speed = ev->GetFloat( 2 );
if ( !speed )
{
speed = 1;
}
targetent = ( Sentient * )ev->GetEntity( 3 );
assert( targetent );
if (!targetent)
{
return;
}
if ( ev->NumArgs() > 3 )
{
grav = ev->GetFloat( 4 );
}
else
{
grav = 1;
}
if ( ev->NumArgs() > 4 )
throw_damage = ev->GetFloat( 5 );
else
throw_damage = 0;
Throw( owner, speed, targetent, grav, throw_damage );
/*
e = new Event( EV_Detach );
ProcessEvent( e );
this->owner = owner->entnum;
edict->ownerNum = owner->entnum;
gravity = grav;
target = targetent->origin;
target.z += targetent->viewheight;
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
edict->clipmask = MASK_PROJECTILE;
dir = target - origin;
xydir = dir;
xydir.z = 0;
traveltime = xydir.length() / speed;
vertical_speed = ( dir.z / traveltime ) + ( 0.5f * gravity * sv_currentGravity->value * traveltime );
xydir.normalize();
// setup ambient flying sound
if ( throw_sound.length() )
{
LoopSound( throw_sound.c_str() );
}
velocity = speed * xydir;
velocity.z = vertical_speed;
angles = velocity.toAngles();
setAngles( angles );
avelocity.x = crandom() * 200;
avelocity.y = crandom() * 200;
takedamage = DAMAGE_YES;
*/
}
void ThrowObject::Pickup( Entity *ent, const str &bone )
{
Event *e;
setOrigin( pickup_offset );
e = new Event( EV_Attach );
e->AddEntity( ent );
e->AddString( bone );
ProcessEvent( e );
hurt_target = false;
edict->s.renderfx &= ~RF_FRAMELERP;
}
void ThrowObject::Pickup( Event *ev )
{
Entity * ent;
//Event * e;
str bone;
ent = ev->GetEntity( 1 );
assert( ent );
if ( !ent )
{
return;
}
bone = ev->GetString( 2 );
/*
setOrigin( pickup_offset );
e = new Event( EV_Attach );
e->AddEntity( ent );
e->AddString( bone );
ProcessEvent( e );
edict->s.renderfx &= ~RF_FRAMELERP;
*/
Pickup( ent , bone );
}