📄 entity.cpp
字号:
return false;
}
if ( !gi.GetBoneTransform( edict->s.modelindex, groupindex, tri_num, orient, edict->s.anim, edict->s.frame,
edict->s.scale, trans, p1 ) )
{
return false;
}
if ( forward || right || up )
{
R_ConcatRotations( trans, orientation, trans );
}
if ( pos )
{
MatrixTransformVector( p1, orientation, p2 );
*pos = Vector( p2 );
}
if ( forward )
{
*forward = Vector( trans[ 0 ] );
}
if ( right )
{
*right = Vector( trans[ 1 ] );
}
if ( up )
{
*up = Vector( trans[ 2 ] );
}
return true;
}
EXPORT_FROM_DLL void Entity::setAngles
(
Vector ang
)
{
Entity * ent;
float mat[3][3];
int num,i;
angles[ 0 ] = angmod( ang[ 0 ] );
angles[ 1 ] = angmod( ang[ 1 ] );
angles[ 2 ] = angmod( ang[ 2 ] );
if ( bindmaster )
{
AnglesToMat( angles.vec3(), mat );
R_ConcatRotations( mat, bindmaster->orientation, orientation );
MatrixToEulerAngles( orientation, worldangles.vec3() );
worldangles.copyTo( edict->s.viewangles );
}
else if (edict->s.parent)
{
float trans[3][3];
float local_trans[3][3];
vec3_t p1;
ent = ( Entity * )G_GetEntity( edict->s.parent );
ang.copyTo( edict->s.viewangles );
if ( gi.GetBoneTransform( ent->edict->s.modelindex, edict->s.bone.group_num, edict->s.bone.tri_num, edict->s.bone.orientation,
ent->edict->s.anim, ent->edict->s.frame, ent->edict->s.scale, trans, p1 ) )
{
AnglesToMat( angles.vec3(), mat );
R_ConcatRotations( mat, trans, local_trans );
R_ConcatRotations( local_trans, ent->orientation, orientation );
MatrixToEulerAngles( orientation, worldangles.vec3() );
}
}
else
{
worldangles = angles;
AnglesToMat( worldangles.vec3(), orientation );
worldangles.copyTo( edict->s.viewangles );
}
worldangles.copyTo( edict->s.angles );
// Fill the edicts matrix
VectorCopy( orientation[ 0 ], edict->s.mat[ 0 ] );
VectorCopy( orientation[ 1 ], edict->s.mat[ 1 ] );
VectorCopy( orientation[ 2 ], edict->s.mat[ 2 ] );
//
// go through and set our children
//
num = numchildren;
for (i=0;(i < MAX_MODEL_CHILDREN) && num;i++)
{
if (!children[i])
continue;
ent = ( Entity * )G_GetEntity( children[i] );
ent->setAngles( ent->angles );
num--;
}
}
EXPORT_FROM_DLL qboolean Entity::droptofloor
(
float maxfall
)
{
trace_t trace;
Vector end;
end = origin;
end[ 2 ]-= maxfall;
origin += "0 0 1";
trace = G_Trace( origin, mins, maxs, end, this, MASK_SOLID, "Entity::droptofloor" );
if ( trace.fraction == 1 || trace.allsolid )
{
groundentity = NULL;
return false;
}
setOrigin( trace.endpos );
groundentity = trace.ent;
groundentity_linkcount = trace.ent->linkcount;
return true;
}
void Entity::Damage
(
Entity *inflictor,
Entity *attacker,
int damage,
Vector position,
Vector direction,
Vector normal,
int knockback,
int dflags,
int meansofdeath,
int groupnum,
int trinum,
float damage_multiplier
)
{
Event *ev;
if ( !attacker )
{
attacker = world;
}
if ( !inflictor )
{
inflictor = world;
}
ev = new Event( EV_Damage );
ev->AddInteger( damage );
ev->AddEntity ( inflictor );
ev->AddEntity ( attacker );
ev->AddVector ( position );
ev->AddVector ( direction );
ev->AddVector ( normal );
ev->AddInteger( knockback );
ev->AddInteger( dflags );
ev->AddInteger( meansofdeath );
ev->AddInteger( groupnum );
ev->AddInteger( trinum );
ev->AddFloat ( damage_multiplier );
ProcessEvent ( ev );
}
void Entity::DamageEvent
(
Event *ev
)
{
Entity *inflictor;
Entity *attacker;
int damage;
Vector dir;
Vector momentum;
Event *event;
float m;
if ( ( takedamage == DAMAGE_NO ) || ( movetype == MOVETYPE_NOCLIP ) )
{
return;
}
damage = ev->GetInteger( 1 );
inflictor = ev->GetEntity( 2 );
attacker = ev->GetEntity( 3 );
// figure momentum add
if ( ( inflictor != world ) &&
( movetype != MOVETYPE_NONE ) &&
( movetype != MOVETYPE_BOUNCE ) &&
( movetype != MOVETYPE_PUSH ) &&
( movetype != MOVETYPE_STOP ) )
{
dir = worldorigin - ( inflictor->worldorigin + ( inflictor->mins + inflictor->maxs ) * 0.5 );
dir.normalize();
if ( mass < 50)
{
m = 50;
}
else
{
m = mass;
}
momentum = dir * damage * ( 1700.0 / m );
velocity += momentum;
}
// check for godmode or invincibility
if ( flags & FL_GODMODE )
{
return;
}
// Forcefields make objects invulnerable
if ( flags & FL_FORCEFIELD )
{
float alpha;
float radius;
Entity *forcefield;
//
// spawn forcefield
//
forcefield = new Entity;
radius = ( centroid - worldorigin ).length();
forcefield->setModel( "sphere2.def" );
forcefield->setOrigin( centroid );
forcefield->worldorigin.copyTo(forcefield->edict->s.old_origin);
forcefield->setMoveType( MOVETYPE_NONE );
forcefield->setSolidType( SOLID_NOT );
forcefield->edict->s.scale = radius / 16;
alpha = damage / 100;
if ( alpha > 1 )
alpha = 1;
if ( alpha < 0.15f )
alpha = 0.15f;
forcefield->edict->s.alpha = alpha;
forcefield->edict->s.renderfx |= RF_TRANSLUCENT;
forcefield->PostEvent( EV_Remove, 0.1f );
return;
}
// team play damage avoidance
//if ( ( global->teamplay == 1 ) && ( edict->team > 0 ) && ( edict->team == attacker->edict->team ) )
// {
// return;
// }
if ( !deathmatch->value && isSubclassOf( Player ) )
{
damage *= 0.15;
}
if ( deadflag )
{
// Check for gib.
if ( inflictor->isSubclassOf( Projectile ) )
{
Event *gibEv;
health -= damage;
gibEv = new Event( EV_Gib );
gibEv->AddEntity( this );
gibEv->AddFloat( health );
ProcessEvent( gibEv );
}
return;
}
// do the damage
health -= damage;
if ( health <= 0 )
{
if ( attacker )
{
event = new Event( EV_GotKill );
event->AddEntity( this );
event->AddInteger( damage );
event->AddEntity( inflictor );
// location based damage
event->AddString( ev->GetString( 4 ) );
event->AddInteger( ev->GetInteger( 9 ) );
event->AddInteger( 0 );
attacker->ProcessEvent( event );
}
event = new Event( EV_Killed );
event->AddEntity( attacker );
event->AddInteger( damage );
event->AddEntity( inflictor );
// location based damage
event->AddString( ev->GetString( 4 ) );
ProcessEvent( event );
return;
}
if (flags & FL_TESSELATE)
{
TesselateModel
(
this,
tess_min_size,
tess_max_size,
dir,
damage,
tess_percentage*0.5f,
tess_thickness,
ev->GetVector( 5 )
);
}
if (flags & FL_DARKEN)
{
edict->s.renderfx |= RF_LIGHTOFFSET;
if ( max_health )
{
edict->s.lightofs = - ( 40.0f * ( (float)(max_health - health) / (float)max_health ) );
}
else
{
edict->s.lightofs -= damage;
}
if ( edict->s.lightofs < -127 )
edict->s.lightofs = -127;
if ( edict->s.lightofs > 127 )
edict->s.lightofs = 127;
}
event = new Event( EV_Pain );
event->AddFloat( damage );
event->AddEntity( attacker );
// location based damage
event->AddString( ev->GetString( 4 ) );
ProcessEvent( event );
}
/*
============
CanDamage
Returns true if the inflictor can directly damage the target. Used for
explosions and melee attacks.
============
*/
qboolean Entity::CanDamage
(
Entity *target
)
{
trace_t trace;
Vector pos;
// bmodels need special checking because their origin is 0,0,0
if ( target->getMoveType() == MOVETYPE_PUSH )
{
pos = ( target->absmin + target->absmax ) * 0.5;
trace = G_Trace( origin, vec_origin, vec_origin, pos, this, MASK_SHOT, "Entity::CanDamage 1" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
return false;
}
trace = G_Trace( origin, vec_origin, vec_origin, target->centroid, this, MASK_SHOT, "Entity::CanDamage 2" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
pos = target->centroid + Vector( 15, 15, 0 );
trace = G_Trace( origin, vec_origin, vec_origin, pos, this, MASK_SHOT, "Entity::CanDamage 3" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
pos = target->centroid + Vector( -15, 15, 0 );
trace = G_Trace( origin, vec_zero, vec_zero, pos, this, MASK_SHOT, "Entity::CanDamage 4" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
pos = target->centroid + Vector( 15, -15, 0 );
trace = G_Trace( origin, vec_zero, vec_zero, pos, this, MASK_SHOT, "Entity::CanDamage 5" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
pos = target->centroid + Vector( -15, -15, 0 );
trace = G_Trace( origin, vec_zero, vec_zero, pos, this, MASK_SHOT, "Entity::CanDamage 6" );
if ( trace.fraction == 1 || trace.ent == target->edict )
{
return true;
}
return false;
}
EXPORT_FROM_DLL qboolean Entity::IsTouching
(
Entity *e1
)
{
if ( e1->absmin.x > absmax.x )
{
return false;
}
if ( e1->absmin.y > absmax.y )
{
return false;
}
if ( e1->absmin.z > absmax.z )
{
return false;
}
if ( e1->absmax.x < absmin.x )
{
return false;
}
if ( e1->absmax.y < absmin.y )
{
return false;
}
if ( e1->absmax.z < absmin.z )
{
return false;
}
return true;
}
void Entity::StopAnimating
(
void
)
{
// Cancel all animating events
last_animation_time = -1;
animating = false;
total_delta = vec_zero;
if ( animDoneEvent )
{
CancelEventsOfType( animDoneEvent );
delete animDoneEvent;
animDoneEvent = NULL;
}
}
void Entity::StartAnimating
(
void
)
{
// start animating
AnimateFrame();
animating = true;
}
void Entity::NextAnim
(
int animnum
)
{
if ( ( animnum >= 0 ) && ( animnum < gi.NumAnims( edict->s.modelindex ) ) )
{
next_anim = animnum;
}
else
{
// bad value
return;
}
// get the next anim delta
gi.Anim_Delta( edict->s.modelindex, next_anim, next_anim_delta.vec3() );
next_anim_delta *= edict->s.scale;
// get the next anim time
next_anim_time = gi.Anim_Time( edict->s.modelindex, next_anim );
NextFrame( 0 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -