?? thrall.cpp
字號:
//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/thrall.cpp $
// $Revision:: 12 $
// $Author:: Aldie $
// $Date:: 11/09/98 12:58a $
//
// 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/thrall.cpp $
//
// 12 11/09/98 12:58a Aldie
// Parentmode for death sequence
//
// 11 11/08/98 8:30p Aldie
// Added gibfest for thrall
//
// 10 10/27/98 10:17p Jimdose
// better aiming by walls
// more damage from pulse
// precached models
//
// 9 10/27/98 5:22p Jimdose
// tweaked him
//
// 8 10/27/98 5:55a Jimdose
// added Chatter
//
// 7 10/27/98 4:55a Jimdose
// NULLed out EV_FadeOut response so that Thrall sticks around
//
// 6 10/27/98 3:52a Jimdose
// got pulse weapon working
//
// 5 10/26/98 2:50p Aldie
// Fixed a bug with checking of NULL owners
//
// 4 10/24/98 3:33a Jimdose
// changed refrences to origin to worldorigin
//
// 3 10/24/98 12:51a Aldie
// Fixed init bug
//
// 2 10/23/98 5:37a Jimdose
// Created file
//
// 1 10/22/98 10:19p Jimdose
//
// DESCRIPTION:
// ThrallMaster
//
#include "g_local.h"
#include "actor.h"
#include "thrall.h"
#include "explosion.h"
#include "vehicle.h"
#include "object.h"
#include "gibs.h"
#define DRUNKMISSILE_SPEED 1000.0f
Event EV_ThrallMaster_FirePulse( "firepulse" );
Event EV_ThrallMaster_FireRockets( "firerockets" );
Event EV_ThrallMaster_GibFest( "gibfest" );
CLASS_DECLARATION( Actor, ThrallMaster, "boss_thrallmaster" );
ResponseDef ThrallMaster::Responses[] =
{
{ &EV_ThrallMaster_FirePulse, ( Response )ThrallMaster::FirePulse },
{ &EV_ThrallMaster_FireRockets, ( Response )ThrallMaster::FireRockets },
{ &EV_Sentient_WeaponUse, ( Response )ThrallMaster::WeaponUse },
{ &EV_ThrallMaster_GibFest, ( Response )ThrallMaster::GibFest },
{ &EV_FadeOut, NULL },
{ NULL, NULL }
};
ThrallMaster::ThrallMaster()
{
modelIndex( "sprites/thrallpulse.spr" );
modelIndex( "view_genbullet.def" );
modelIndex( "trocket.def" );
modelIndex( "thrallfire.def" );
setModel( "thrall.def" );
weaponmode = PRIMARY;
gunbone = "gun";
flags |= FL_NOION;
}
Vector ThrallMaster::GunPosition
(
void
)
{
vec3_t trans[ 3 ];
vec3_t orient;
int groupindex;
int tri_num;
Vector offset = vec_zero;
Vector result;
// get the gun position of the actor
if ( !gi.GetBoneInfo( edict->s.modelindex, gunbone.c_str(), &groupindex, &tri_num, orient ) )
{
// Gun doesn't have a barrel, just return the default
return worldorigin + gunoffset;
}
gi.GetBoneTransform( edict->s.modelindex, groupindex, tri_num, orient, edict->s.anim,
edict->s.frame, edict->s.scale, trans, offset.vec3() );
MatrixTransformVector( offset.vec3(), orientation, result.vec3() );
result += worldorigin;
return result;
}
qboolean ThrallMaster::CanShootFrom
(
Vector pos,
Entity *ent,
qboolean usecurrentangles
)
{
int mask;
Vector delta;
Vector start;
Vector end;
float len;
trace_t trace;
Vehicle *v;
Entity *t;
Vector ang;
if ( !currentWeapon || !WithinDistance( ent, vision_distance ) )
{
if (!currentWeapon && !has_melee )
return false;
}
if ( usecurrentangles )
{
Vector dir;
start = pos + GunPosition() - worldorigin;
end = ent->centroid;
end.z += ( ent->absmax.z - ent->centroid.z ) * 0.75f;
delta = end - start;
ang = delta.toAngles();
ang.x = -ang.x;
ang.y = angles.y;
len = delta.length();
ang.AngleVectors( &dir, NULL, NULL );
dir *= len;
end = start + dir;
}
else
{
vec3_t trans[ 3 ];
vec3_t transtemp[ 3 ];
vec3_t orient;
int groupindex;
int tri_num;
Vector offset = vec_zero;
Vector result;
// endpos
end = ent->centroid;
end.z += ( ent->absmax.z - ent->centroid.z ) * 0.75f;
// get the gun position of the actor
if ( !gi.GetBoneInfo( edict->s.modelindex, gunbone.c_str(), &groupindex, &tri_num, orient ) )
{
// Gun doesn't have a barrel, just return the default
result = gunoffset;
}
else
{
Vector forward, right, up;
// get new forward vec
forward = end - worldorigin;
forward.z = 0;
forward.normalize();
forward.copyTo( trans[ 0 ] );
// new right vec
right.x = -forward.y;
right.y = forward.x;
right.z = 0;
right.copyTo( trans[ 1 ] );
// new up vec
up.x = 0;
up.y = 0;
up.z = 1;
up.copyTo( trans[ 2 ] );
gi.GetBoneTransform( edict->s.modelindex, groupindex, tri_num, orient, edict->s.anim,
edict->s.frame, edict->s.scale, transtemp, offset.vec3() );
MatrixTransformVector( offset.vec3(), trans, result.vec3() );
}
start = pos + result;
delta = end - start;
len = delta.length();
}
// check if we're too far away, or too close
if ( currentWeapon )
{
if ( ( len > attack_range ) || ( len > currentWeapon->GetMaxRange() ) || ( len < currentWeapon->GetMinRange() ) )
{
return false;
}
mask = MASK_SHOT;
}
else
{
if ( ( len > attack_range ) || ( len > melee_range ) )
{
return false;
}
mask = MASK_PROJECTILE;
}
// shoot past the guy we're shooting at
end += delta * 4;
// Check if he's visible
trace = G_Trace( start, vec_zero, vec_zero, end, this, mask, "Actor::CanShootFrom" );
if ( trace.startsolid )
{
return false;
}
// If we hit the guy we wanted, then shoot
if ( trace.ent == ent->edict )
{
return true;
}
// if we hit a vehicle, check if the driver is someone we want to hit
t = trace.ent->entity;
if ( t && t->isSubclassOf( Vehicle ) )
{
v = ( Vehicle * )t;
if ( ( v->Driver() == ent ) || IsEnemy( v->Driver() ) )
{
return true;
}
return false;
}
// If we hit someone else we don't like, then shoot
if ( IsEnemy( t ) )
{
return true;
}
// if we hit something breakable, check if shooting it will
// let us shoot someone.
if ( t->isSubclassOf( Shatter ) ||
t->isSubclassOf( Object ) ||
t->isSubclassOf( DamageThreshold ) ||
t->isSubclassOf( ScriptModel ) )
{
trace = G_Trace( Vector( trace.endpos ), vec_zero, vec_zero, end, t, mask, "Actor::CanShootFrom 2" );
if ( trace.startsolid )
{
return false;
}
// If we hit the guy we wanted, then shoot
if ( trace.ent == ent->edict )
{
return true;
}
// If we hit someone else we don't like, then shoot
if ( IsEnemy( trace.ent->entity ) )
{
return true;
}
// Forget it then
return false;
}
return false;
}
void ThrallMaster::Chatter
(
const char *snd,
float chance,
float volume,
int channel
)
{
if ( chattime > level.time )
{
return;
}
RandomSound( snd, volume, channel, ATTN_NONE );
chattime = level.time + 7 + G_Random( 5 );
}
void ThrallMaster::WeaponUse
(
Event *ev
)
{
Sentient::WeaponUse( ev );
if ( weaponmode == PRIMARY )
{
weaponmode = SECONDARY;
gunbone = "chest";
}
else
{
weaponmode = PRIMARY;
gunbone = "gun";
}
}
void ThrallMaster::GibFest
(
Event *ev
)
{
Vector pos;
Gib *gib1, *gib2;
if ( sv_gibs->value && !parentmode->value )
{
GetBone( "chest", &pos, NULL, NULL, NULL );
pos += worldorigin;
gib1 = new Gib( "gib1.def" );
gib1->setOrigin(pos);
gib1->worldorigin.copyTo(gib1->edict->s.old_origin);
gib1->SetVelocity( 1000 );
gib1->velocity *= 3;
gib1->edict->s.scale = 3.0;
gib1->fadesplat = false;
gib2 = new Gib( "gib2.def" );
gib2->setOrigin(pos);
gib2->worldorigin.copyTo(gib2->edict->s.old_origin);
gib2->SetVelocity( 1000 );
gib2->velocity *= 3;
gib2->edict->s.scale = 3.0;
gib2->fadesplat = false;
}
}
void ThrallMaster::FirePulse
(
Event *ev
)
{
if ( ( currentWeapon ) && currentWeapon->ReadyToFire() && currentWeapon->HasAmmo() )
{
weaponmode = SECONDARY;
currentWeapon->Fire();
}
}
void ThrallMaster::FireRockets
(
Event *ev
)
{
if ( ( currentWeapon ) && currentWeapon->ReadyToFire() && currentWeapon->HasAmmo() )
{
weaponmode = PRIMARY;
currentWeapon->Fire();
}
}
CLASS_DECLARATION( Weapon, ThrallGun, NULL );
ResponseDef ThrallGun::Responses[] =
{
{ &EV_Weapon_Shoot, ( Response )ThrallGun::Shoot },
{ &EV_Weapon_SecondaryUse, ( Response )ThrallGun::SecondaryUse },
{ NULL, NULL }
};
ThrallGun::ThrallGun()
{
SetModels( NULL, "view_genbullet.def" );
SetAmmo( "Rockets", 1, 10 );
}
void ThrallGun::Shoot
(
Event *ev
)
{
DrunkMissile *missile;
ThrallPulse *pulse;
Vector pos;
Vector dir;
assert( owner );
if ( !owner )
{
return;
}
GetMuzzlePosition( &pos, &dir );
if ( weaponmode == PRIMARY )
{
missile = new DrunkMissile;
missile->Setup( owner, pos, dir );
NextAttack( 0 );
}
else
{
pulse = new ThrallPulse;
pulse->Setup( owner, pos, dir );
NextAttack( 0 );
}
}
void ThrallGun::SecondaryUse
(
Event *ev
)
{
if ( weaponmode == PRIMARY )
{
weaponmode = SECONDARY;
}
else
{
weaponmode = PRIMARY;
}
}
Event EV_DrunkMissile_HeatSeek( "heatseek" );
CLASS_DECLARATION( Projectile, DrunkMissile, NULL );
ResponseDef DrunkMissile::Responses[] =
{
{ &EV_Touch, ( Response )DrunkMissile::Explode },
{ &EV_DrunkMissile_HeatSeek, ( Response )DrunkMissile::HeatSeek },
{ NULL, NULL }
};
EXPORT_FROM_DLL void DrunkMissile::Explode
(
Event *ev
)
{
int damg;
Vector v;
Entity *other;
Entity *owner;
other = ev->GetEntity( 1 );
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -