quadrilateralcowboy/d3xp/clock.cpp
2020-06-12 14:06:25 -07:00

284 lines
No EOL
6.2 KiB
C++

#include "../idlib/precompiled.h"
#pragma hdrstop
#include "Game_local.h"
#define OFFSET_MULTIPLIER 60000
const idEventDef EV_clockreset( "clockreset" );
const idEventDef EV_clocksettime( "clocksettime", "d" );
CLASS_DECLARATION( idAnimatedEntity, idClock )
EVENT( EV_clockreset, idClock::Event_reset)
EVENT( EV_clocksettime, idClock::Event_setTime)
END_CLASS
void idClock::Save( idSaveGame *savefile ) const
{
savefile->WriteBool(digital);
savefile->WriteInt(startTime);
savefile->WriteInt(offsetTime);
savefile->WriteInt(lastMinuteCount);
savefile->WriteFloat(startAngle);
savefile->WriteFloat(endAngle);
savefile->WriteInt(minuteStartTime);
savefile->WriteInt(minuteEndTime);
savefile->WriteInt(nextSecondsInterval);
savefile->WriteInt(secondsLerpStart);
savefile->WriteInt(secondsLerpEnd);
savefile->WriteInt(secondsState);
savefile->WriteInt(secondsAngleStart);
savefile->WriteInt(secondsAngleEnd);
}
void idClock::Restore( idRestoreGame *savefile )
{
savefile->ReadBool(digital);
savefile->ReadInt(startTime);
savefile->ReadInt(offsetTime);
savefile->ReadInt(lastMinuteCount);
savefile->ReadFloat(startAngle);
savefile->ReadFloat(endAngle);
savefile->ReadInt(minuteStartTime);
savefile->ReadInt(minuteEndTime);
savefile->ReadInt(nextSecondsInterval);
savefile->ReadInt(secondsLerpStart);
savefile->ReadInt(secondsLerpEnd);
savefile->ReadInt(secondsState);
savefile->ReadInt(secondsAngleStart);
savefile->ReadInt(secondsAngleEnd);
}
void idClock::Spawn( void )
{
digital = spawnArgs.GetBool("digital", "0");
this->GetPhysics()->SetContents(0);
this->startTime = 0;
lastMinuteCount = 0;
startAngle = 0;
endAngle = 0;
minuteStartTime = 0;
minuteEndTime = 0;
nextSecondsInterval = 0;
secondsLerpStart = 0;
secondsLerpEnd = 0;
secondsState = 0;
secondsAngleStart = 0;
secondsAngleEnd = 0;
offsetTime = spawnArgs.GetInt("offset", "0") * OFFSET_MULTIPLIER;
BecomeActive( TH_THINK );
}
void idClock::Event_setTime( int time )
{
//this->startTime = gameLocal.time - (time * 1000);
offsetTime = time * 1000;
}
void idClock::Event_reset( void )
{
lastMinuteCount = 0;
startAngle = 0;
endAngle = 0;
minuteStartTime = 0;
minuteEndTime = 0;
nextSecondsInterval = 0;
secondsLerpStart = 0;
secondsLerpEnd = 0;
secondsState = 0;
secondsAngleStart = 0;
secondsAngleEnd = 0;
offsetTime = spawnArgs.GetInt("offset", "0") * OFFSET_MULTIPLIER;
this->startTime = gameLocal.time;
SetHandAngle("minute", 0);
SetHandAngle("hour", 0);
SetHandAngle("second", 0);
}
void idClock::SetHandAngle( const char *jointName, float angle )
{
idMat3 bodyAxis;
idVec3 offset;
jointHandle_t originJoint = animator.GetJointHandle( "origin" );
animator.GetJointTransform( originJoint, gameLocal.time, offset, bodyAxis );
jointHandle_t secondJoint;
idRotation secondRotation;
secondJoint = animator.GetJointHandle( jointName );
secondRotation.SetVec( bodyAxis[0] );
secondRotation.SetAngle( angle );
animator.SetJointAxis(secondJoint, JOINTMOD_WORLD, secondRotation.ToMat3());
}
void idClock::Think( void )
{
int curTime = (gameLocal.time - startTime) + offsetTime;
//common->Printf("curtime %d\n", curTime);
if (!digital)
{
//SET SECONDS.
int totalMinutes = (int)(curTime / 1000.0f);
int secondsFraction = curTime - totalMinutes;
float secondsPercentage = secondsFraction / 1000.0f;
float secondsAngle = secondsPercentage * 6.0f;
//gameLocal.GetLocalPlayer()->DebugMessage(va("%d", secondsFraction));
//secondsState 0 = idle. 1 = lerping.
if (gameLocal.time > nextSecondsInterval)
{
secondsState = 1;
nextSecondsInterval = gameLocal.time + 1000;
//SetHandAngle("second", secondsAngle);
secondsAngleStart = secondsAngleEnd;
secondsAngleEnd = secondsAngle;
secondsLerpStart = gameLocal.time;
secondsLerpEnd = gameLocal.time + 100;
StartSound( "snd_tick", SND_CHANNEL_ANY, 0, false, NULL );
}
if (secondsState == 1)
{
float lerp;
float currentTime = gameLocal.time;
float lookTimeMax = this->secondsLerpEnd - this->secondsLerpStart;
currentTime -= this->secondsLerpStart;
lerp = currentTime / lookTimeMax;
if (lerp >= 1)
{
lerp = 1;
secondsState = 0;
}
SetHandAngle("second", idMath::Lerp(secondsAngleStart, secondsAngleEnd, lerp));
}
//SET MINUTES. (discrete movement)
int minuteCount = totalMinutes / 60;
//gameLocal.GetLocalPlayer()->DebugMessage(va("time %d", minuteCount));
if (minuteCount > 60)
{
int i;
for (i = 0; i < 999; i++)
{
if (minuteCount > 60)
minuteCount -= 60;
else
break;
}
}
if (minuteCount != lastMinuteCount)
{
minuteStartTime = gameLocal.time;
minuteEndTime = gameLocal.time + 300;
startAngle = endAngle;
endAngle = 360.0f * (minuteCount / 60.0f);
lastMinuteCount = minuteCount;
StartSound( "snd_minute", SND_CHANNEL_ANY, 0, false, NULL );
//hack. force the second hand to reset.
secondsAngleStart = secondsAngle;
secondsAngleEnd = secondsAngle;
secondsLerpStart = gameLocal.time;
secondsLerpEnd = gameLocal.time + 50;
secondsState = 1;
nextSecondsInterval = gameLocal.time + 1000;
}
if (minuteEndTime >= gameLocal.time)
{
float lerp;
float currentTime = gameLocal.time;
float lookTimeMax = this->minuteEndTime - this->minuteStartTime;
currentTime -= this->minuteStartTime;
lerp = currentTime / lookTimeMax;
//gameLocal.Printf(va("time %f", lerp));
if (lerp > 1)
lerp = 1;
SetHandAngle("minute", idMath::Lerp(startAngle, endAngle, lerp));
}
//SET HOURS.
float hourAngle = secondsPercentage * 0.001666666666666f;
SetHandAngle("hour", hourAngle);
}
else
{
//digital.
int fullHours = curTime / 3600000;
int fullMinutes = curTime / 60000;
if (fullHours > 0)
{
fullMinutes -= fullHours * 60;
}
int seconds = curTime / 1000;
if (fullMinutes > 0)
{
seconds -= fullMinutes * 60;
}
if (fullHours > 0)
{
seconds -= (fullHours * 60) * 60;
}
this->renderEntity.gui[0]->SetStateString("gui_parm0", va("%02d", fullHours));
this->renderEntity.gui[0]->SetStateString("gui_parm1", va("%02d", fullMinutes));
this->renderEntity.gui[0]->SetStateString("gui_parm2", va("%02d", seconds));
}
//idAnimatedEntity::Think();
idAnimatedEntity::Present();
}