123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702 |
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- #define WALKSPEED 9 //was 9
- #define WALKBOUNCE 6 //if hit an obstacle then bounce a bit to dislodge itself.
- #define DIST_MOD 0.11f
- #define MAXPITCH 50
- #define MAXROLL 50
- #define OFFROADTIME 200
- #define JUMPDISTANCE 192
- #define JUMPHEIGHT 256
- #define PLUGMOVETIME 0.2f
- #define JUMP_STARTTIME 400
- const idEventDef EV_weevil_forward( "weevilforward", "d" );
- const idEventDef EV_weevil_turn( "weevilturn", "d" );
- const idEventDef EV_weevil_stop( "weevilstop" );
- const idEventDef EV_weevil_stand( "weevilstand" );
- const idEventDef EV_weevil_light( "weevillight", "d" );
- const idEventDef EV_weevil_jump( "weeviljump" );
- const idEventDef EV_weevil_gravity( "weevilgravity", "d" );
- const idEventDef EV_weevil_getgravity( "weevilgetgravity", NULL, 'd' );
- const idEventDef EV_weevil_doplug( "weevildoplug", "de" );
- const idEventDef EV_weevil_plugConnected( "<weevilPlugConnected>", "v" );
- const idEventDef EV_weevil_isPlugConnected( "isweevilplugconnected", NULL, 'd' );
- const idEventDef EV_weevil_eyemove("weevileyemove", "ffd", 'd');
- CLASS_DECLARATION( idMoveableItem, idWeevil )
- EVENT( EV_weevil_forward, idWeevil::Event_forward )
- EVENT( EV_weevil_turn, idWeevil::Event_turn )
- EVENT( EV_weevil_stop, idWeevil::Event_stop )
- EVENT( EV_weevil_stand, idWeevil::Event_stand )
- EVENT( EV_weevil_light, idWeevil::Event_light )
- EVENT( EV_weevil_jump, idWeevil::Event_jump )
- EVENT( EV_weevil_gravity, idWeevil::Event_gravity )
- EVENT( EV_weevil_getgravity, idWeevil::Event_getgravity )
- EVENT( EV_weevil_doplug, idWeevil::Event_doPlug )
- EVENT( EV_weevil_plugConnected, idWeevil::Event_plugdone)
- EVENT( EV_weevil_isPlugConnected, idWeevil::Event_isweevilplugconnected)
- EVENT( EV_weevil_eyemove, idWeevil::Event_weevilEyeMove)
- END_CLASS
- void idWeevil::Save( idSaveGame *savefile ) const
- {
- savefile->WriteBool(isGravity);
- savefile->WriteInt(state);
- savefile->WriteInt(walkDirection);
- savefile->WriteInt(turnCurrent);
- savefile->WriteInt(turnTarget);
- savefile->WriteInt(turnDirection);
- savefile->WriteInt(offroadTimer);
- savefile->WriteInt(jumpstartTimer);
- savefile->WriteVec3(lastPosition);
- savefile->WriteObject(model);
- savefile->WriteObject(nosecam);
- savefile->WriteObject(light);
- savefile->WriteObject(plugModel);
- savefile->WriteObject(beamStart);
- savefile->WriteObject(beamEnd);
- savefile->WriteJoint(headJoint);
- }
- void idWeevil::Restore( idRestoreGame *savefile )
- {
- savefile->ReadBool(isGravity);
- savefile->ReadInt(state);
- savefile->ReadInt(walkDirection);
- savefile->ReadInt(turnCurrent);
- savefile->ReadInt(turnTarget);
- savefile->ReadInt(turnDirection);
- savefile->ReadInt(offroadTimer);
- savefile->ReadInt(jumpstartTimer);
- savefile->ReadVec3(lastPosition);
- savefile->ReadObject(reinterpret_cast<idClass *&>(model));
- savefile->ReadObject(reinterpret_cast<idClass *&>(nosecam));
- savefile->ReadObject(reinterpret_cast<idClass *&>(light));
- savefile->ReadObject(reinterpret_cast<idClass *&>(plugModel));
- savefile->ReadObject(reinterpret_cast<idClass *&>(beamStart));
- savefile->ReadObject(reinterpret_cast<idClass *&>(beamEnd));
- savefile->ReadJoint(headJoint);
- }
- void idWeevil::Spawn( void )
- {
- idDict args;
-
- jointHandle_t noseJoint;
- idVec3 nosePos;
- idMat3 noseAxis;
- idVec3 forward;
- state = 0;
- walkDirection = 1;
- turnCurrent = 0;
- turnTarget = 0;
- turnDirection = 1;
- offroadTimer = 0;
- jumpstartTimer = 0;
- lastPosition = vec3_zero;
- isGravity = true;
- BecomeActive( TH_THINK );
- //MODEL
- this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward);
- args.Clear();
- args.SetVector( "origin", this->GetPhysics()->GetOrigin() );
- args.Set( "model", "monster_weevil" );
- args.Set( "cycle", "-1" );
- //args.Set( "notriggeronanim", "1" );
- model = ( idAnimatedEntity * )gameLocal.SpawnEntityType( idAnimatedEntity::Type, &args );
- model->SetAxis( this->GetPhysics()->GetAxis() );
- // BEAMS / PLUGS
- args.Clear();
- args.Set( "model", "models/datajack_plug/tris.ase" );
- args.SetBool( "solid", 0);
- plugModel = ( idMover * )gameLocal.SpawnEntityType( idMover::Type, &args );
- plugModel->Hide();
- args.Clear();
- args.SetInt( "start_off", 1);
- beamEnd = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type );
- args.Clear();
- args.Set( "target", beamEnd->name.c_str() );
- args.Set( "skin", "skins/beam_black");
- args.SetInt( "start_off", 1);
- beamStart = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
- beamStart->Hide();
- beamStart->Event_SetWidth(0.5f);
- idVec3 selfForward, selfUp;
- idAngles selfAng = this->GetPhysics()->GetAxis().ToAngles();
- selfAng.ToVectors(&selfForward, NULL, &selfUp);
- idVec3 attachPoint = this->GetPhysics()->GetOrigin() + (selfForward * -3) + (selfUp * 7);
- beamStart->SetOrigin(attachPoint );
- beamStart->Bind( this, false );
- idVec3 plugForward;
- idAngles plugAng = plugModel->GetPhysics()->GetAxis().ToAngles();
- selfAng.ToVectors(&plugForward, NULL, NULL);
- idVec3 plugEndPoint = plugModel->GetPhysics()->GetOrigin() + (plugForward * 0.9f);
- beamEnd->SetOrigin(plugEndPoint);
- beamEnd->Bind(plugModel, false);
- beamEnd->Hide();
- model->Bind(this, true);
-
- //nose camera.
- noseJoint = model->GetAnimator()->GetJointHandle( "head" );
- model->GetAnimator()->GetJointTransform( noseJoint, gameLocal.time, nosePos, noseAxis );
- args.Clear();
- args.SetVector( "origin", nosePos + this->GetPhysics()->GetOrigin() + (forward * -2));
- args.Set( "classname", "func_cameraview" );
- gameLocal.SpawnEntityDef( args, &nosecam );
- nosecam->BindToJoint(model, noseJoint, true);
- nosecam->BecomeActive(TH_PHYSICS);
- this->spawnArgs.Set("nosecamera_name", nosecam->GetName());
- //spawn light.
- args.Clear();
- args.SetVector( "origin", nosePos + this->GetPhysics()->GetOrigin() + (forward * 0.9f) );
- args.Set( "light_target", "1 0 -0.3" );
- args.Set( "light_up", "0 0 1" );
- args.Set( "light_right", "0 -1.5 0" );
- args.Set( "light_end", "128 0 0" );
- args.Set( "texture", "lights/monitorglow" );
- args.Set("start_off", "1");
- args.SetInt("alarmlight", 0);
- light = ( idLight * )gameLocal.SpawnEntityType( idLight::Type, &args );
- light->Bind(this, true);
-
- headJoint = model->GetAnimator()->GetJointHandle( "head" );
-
- }
- bool idWeevil::isJumping( void )
- {
- if (jumpstartTimer > gameLocal.time)
- return true;
- return false;
- }
- void idWeevil::OnGet( void )
- {
- gameLocal.KillCCTVs();
- beamStart->PostEventMS( &EV_Remove, 0 );
- beamEnd->PostEventMS( &EV_Remove, 0 );
- plugModel->PostEventMS( &EV_Remove, 0 );
- }
- void idWeevil::Event_isweevilplugconnected( void )
- {
- if (plugModel->IsHidden())
- idThread::ReturnInt(0);
- else
- idThread::ReturnInt(1);
- }
- void idWeevil::Event_plugdone( idVec3 const &position )
- {
- idDict args;
- args.Clear();
- args.SetVector( "origin", position );
- args.Set( "model", spawnArgs.GetString("smoke_plug", "plugconnect.prt") );
- args.SetBool( "start_off", false );
- gameLocal.SpawnEntityType( idExplodable::Type, &args );
- StartSound( "snd_plugin", SND_CHANNEL_ANY, 0, false, NULL );
- }
- void idWeevil::Event_doPlug( int active, idEntity *jackEnt )
- {
- if (active <= 0)
- {
- //unplug.
- beamStart->Hide();
- plugModel->Hide();
- return;
- }
- //plug in.
- plugModel->GetPhysics()->SetAxis( jackEnt->GetPhysics()->GetAxis() );
- idVec3 jackForward, jackUp;
- idAngles selfAng = jackEnt->GetPhysics()->GetAxis().ToAngles();
- selfAng.ToVectors(&jackForward, NULL, &jackUp);
- idVec3 jackEndPos = jackEnt->GetPhysics()->GetOrigin() + (jackForward * 0.4) + (jackUp * 1.1);
-
- //gameRenderWorld->DebugLine(idVec4(0,1,0,1), plugModel->GetPhysics()->GetOrigin(), plugModel->GetPhysics()->GetOrigin() + idVec3(0,0,128), 10000);
- //gameRenderWorld->DebugLine(idVec4(1,1,0,1), jackEndPos, jackEndPos + idVec3(0,0,128), 10000);
- idVec3 weevilUp;
- idAngles weevilAng = this->GetPhysics()->GetAxis().ToAngles();
- weevilAng.ToVectors(NULL, NULL, &weevilUp);
- plugModel->SetOrigin( this->GetPhysics()->GetOrigin() + (weevilUp * 6) );
- plugModel->Event_SetMoveTime(PLUGMOVETIME);
- plugModel->Event_MoveToPos(jackEndPos);
- PostEventSec( &EV_weevil_plugConnected, PLUGMOVETIME, jackEndPos);
-
- beamEnd->Show();
- beamStart->Show();
- plugModel->Show();
- }
- void idWeevil::Event_jump( void )
- {
- Event_stand();
- state = JUMPSTART;
- this->Event_PlayAnim("jump_start", false);
- jumpstartTimer = gameLocal.time + JUMP_STARTTIME;
- StartSound( "snd_jump", SND_CHANNEL_ANY, 0, false, NULL );
- }
- void idWeevil::Event_getgravity( )
- {
- if (this->isGravity <= 0)
- {
- idThread::ReturnInt( 0 );
- }
- else
- {
- idThread::ReturnInt( 1 );
- }
- }
- void idWeevil::Event_gravity( int value )
- {
- if (value <= 0)
- {
- //gravity is now OFF.
- this->isGravity = 0;
- lastGravityState = false;
- }
- else
- {
- //turn on gravity.
- this->isGravity = 1;
- }
- if (value >= 1)
- {
- //turn on gravity.
- physicsObj.SetGravity( gameLocal.GetGravity() );
- }
- }
- void idWeevil::Event_light( int value )
- {
- if (value)
- {
- if ( !light->isOn )
- {
- StartSound( "snd_light", SND_CHANNEL_ANY, 0, false, NULL );
- }
- light->On();
- }
- else
- {
- if ( light->isOn )
- {
- StartSound( "snd_light", SND_CHANNEL_ANY, 0, false, NULL );
- }
- light->Off();
- }
- }
- void idWeevil::Event_stand( void )
- {
- CancelEvents( &EV_weevil_stop );
- state = IDLE;
- if (!isGravity)
- {
- return;
- }
- idAngles ang = this->GetPhysics()->GetAxis().ToAngles();
- ang.pitch = 0;
- ang.roll = 0;
- this->GetPhysics()->SetAxis( ang.ToMat3() );
- this->SetOrigin(this->GetPhysics()->GetOrigin() + idVec3(0,0,3.0f));
- StartSound( "snd_stand", SND_CHANNEL_ANY, 0, false, NULL );
- }
- void idWeevil::Event_turn( int degrees )
- {
- if (degrees == 0)
- {
- return;
- }
- CancelEvents( &EV_weevil_stop );
- state = TURNING;
- turnCurrent = 0;
- turnTarget = idMath::Abs(degrees);
- if (degrees > 0)
- {
- turnDirection = -1;
-
- }
- else
- {
- turnDirection = 1;
- }
- Event_PlayAnim("turning", true);
- //this->Event_PlayAnim( "idle", false );
- }
- void idWeevil::Event_forward( int distance )
- {
- if (distance == 0)
- {
- return;
- }
- CancelEvents( &EV_weevil_stop );
- if (distance > 0)
- {
- walkDirection = 1;
- Event_PlayAnim("walk", true);
- }
- else
- {
- walkDirection = -1;
- Event_PlayAnim("walkbackwards", true);
- }
- offroadTimer = gameLocal.time + OFFROADTIME;
- state = WALKING;
-
- PostEventSec( &EV_weevil_stop, idMath::Abs(distance) * DIST_MOD );
- }
- void idWeevil::Event_stop( void )
- {
- CancelEvents( &EV_weevil_stop );
- state = IDLE;
- Event_PlayAnim("idle", false);
- }
- void idWeevil::UpdateStates( void )
- {
- if (state == WALKING)
- {
- if (CanMove())
- {
- idVec3 curPos;
- float bounceAmount;
- idVec3 forward;
- this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward);
- forward.Normalize();
- curPos = this->GetPhysics()->GetOrigin();
- if (HasObstacle() ||
- (idMath::Fabs(lastPosition.x - curPos.x) < 0.0001f
- && idMath::Fabs(lastPosition.y - curPos.y) < 0.0001f
- && idMath::Fabs(lastPosition.z - curPos.z) < 0.0001f))
- {
- //"off-road" mode.
- bounceAmount = WALKBOUNCE;
- }
- else
- {
- //normal walk.
- bounceAmount = 0;
- }
- this->GetPhysics()->SetLinearVelocity(forward * (WALKSPEED * walkDirection) + (idVec3(0,0,1) * bounceAmount));
- lastPosition.x = curPos.x;
- lastPosition.y = curPos.y;
- lastPosition.z = curPos.z;
- }
- }
- else if (state == TURNING)
- {
- idAngles ang = this->GetPhysics()->GetAxis().ToAngles();
- ang.yaw += turnDirection;
- turnCurrent++;
- if (turnCurrent >= turnTarget)
- {
- Event_stop();
- return;
- }
- if (CanMove())
- {
- this->GetPhysics()->SetAxis( ang.ToMat3() );
- }
- }
- else if (state == JUMPSTART)
- {
- if (gameLocal.time > jumpstartTimer)
- {
- idVec3 forward;
- idAngles ang = this->GetPhysics()->GetAxis().ToAngles();
- ang.pitch = 0;
- ang.roll = 0;
- ang.ToVectors(&forward);
- if (this->GetPhysics()->HasGroundContacts())
- {
- Event_stand();
- this->GetPhysics()->SetLinearVelocity((forward * JUMPDISTANCE) + (idVec3(0,0,1) * JUMPHEIGHT));
- }
- this->Event_PlayAnim( "jump_loop", true );
- state = JUMPING;
- jumpstartTimer = gameLocal.time + 200; //guarantee some jump time before it is allowed to enter landing state.
- }
- }
- else if (state == JUMPING)
- {
- if (this->IsGrabbed())
- {
- state = IDLE;
- return;
- }
- if (this->GetPhysics()->HasGroundContacts() && gameLocal.time > jumpstartTimer)
- {
- state = IDLE;
-
- Event_stand();
- this->GetPhysics()->PutToRest();
- this->Event_PlayAnim( "jump_end", false );
- return;
- }
- }
- }
- bool idWeevil::HasObstacle( void )
- {
- trace_t forwardTr;
- idVec3 forward, up, right;
- idVec3 traceStart;
- trace_t downTr1, downTr2, downTr3;
-
- this->GetPhysics()->GetAxis().ToAngles().ToVectors(&forward, &right, &up);
-
- traceStart = this->GetPhysics()->GetOrigin() + (up * 1);
- gameLocal.clip.TracePoint( forwardTr, traceStart, traceStart + (forward * (16 * walkDirection)), MASK_SOLID, this );
- if (forwardTr.fraction < 1)
- {
- return true;
- }
- //do the down trace to see if weevil is on a pit.
- gameLocal.clip.TracePoint( downTr1, traceStart + (forward * 5), traceStart + (forward * 5) + (up * -3), MASK_SOLID, this );
- if (downTr1.fraction >= 1)
- {
- return true;
- }
- gameLocal.clip.TracePoint( downTr2, traceStart + (forward * -5), traceStart + (forward * -5) + (up * -3), MASK_SOLID, this );
- if (downTr2.fraction >= 1)
- {
- return true;
- }
- gameLocal.clip.TracePoint( downTr3, traceStart, traceStart + (up * -3), MASK_SOLID, this );
- if (downTr3.fraction >= 1)
- {
- return true;
- }
- return false;
- }
- bool idWeevil::CanMove( void )
- {
- idAngles angles = this->GetPhysics()->GetAxis().ToAngles();
- //return false if: being held, not touching ground, pitch is tilted far, roll is tilted far.
- if (this->IsGrabbed() || !this->GetPhysics()->HasGroundContacts() || idMath::Abs( angles.pitch) >= MAXPITCH || idMath::Abs(angles.roll) >= MAXROLL)
- {
- return false;
- }
- return true;
- }
- void idWeevil::Think( void )
- {
- //RunPhysics();
- if (touchTriggers)
- {
- TouchTriggers();
- }
- //for the vacuum check.
- //if (!isGravity)
- {
- idMoveableItem::Think();
- }
- UpdateStates();
- Present();
- }
- void idWeevil::Present( void )
- {
- // don't present to the renderer if the entity hasn't changed
- if ( !( thinkFlags & TH_UPDATEVISUALS ) )
- {
- return;
- }
- BecomeInactive( TH_UPDATEVISUALS );
-
- // if set to invisible, skip
- if ( !renderEntity.hModel || IsHidden() )
- {
- return;
- }
- // add to refresh list
- if ( modelDefHandle == -1 )
- {
- modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
- }
- else
- {
- gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
- }
- }
- void idWeevil::Event_PlayAnim( const char* animname, bool cycle)
- {
- int anim;
- int channel = 0;
- int animBlendFrames = 4;
- int animDoneTime = 0;
- anim = model->GetAnimator()->GetAnim( animname );
- if ( !anim )
- {
- gameLocal.Warning( "missing '%s' animation on '%s' (%s)", animname, name.c_str(), GetEntityDefName() );
- model->GetAnimator()->Clear( channel, gameLocal.time, FRAME2MS( animBlendFrames ) );
- animDoneTime = 0;
- }
- else
- {
- if (cycle)
- {
- model->GetAnimator()->CycleAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
- }
- else
- {
- model->GetAnimator()->PlayAnim( channel, anim, gameLocal.time, FRAME2MS( animBlendFrames ) );
- }
- animDoneTime = model->GetAnimator()->CurrentAnim( channel )->GetEndTime();
- }
- animBlendFrames = 0;
- }
- void idWeevil::Event_weevilEyeMove(float pitch, float yaw, bool reset)
- {
- if (reset)
- {
- headAngle = idAngles(0,0,0);
- model->GetAnimator()->SetJointAxis(headJoint, JOINTMOD_WORLD, headAngle.ToMat3());
- idThread::ReturnInt(1);
- return;
- }
-
- float newYaw = idMath::ClampFloat(-90, 90, headAngle.yaw - yaw);
- float newPitch = idMath::ClampFloat(-90, 90, headAngle.roll + pitch);
- if (idMath::Fabs(headAngle.roll) + idMath::Fabs(pitch) > 90 || idMath::Fabs(headAngle.yaw) + idMath::Fabs(yaw) > 90)
- {
- idThread::ReturnInt(0);
- }
- else
- {
- idThread::ReturnInt(1);
- }
- headAngle.roll = newPitch;
- headAngle.yaw = newYaw;
- model->GetAnimator()->SetJointAxis(headJoint, JOINTMOD_LOCAL, headAngle.ToMat3());
- }
|