sin-2015/viewthing.cpp

744 lines
18 KiB
C++
Raw Normal View History

1999-04-22 00:00:00 +00:00
// Copyright (C) 1997 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:
// Actor code for the Viewthing.
//
#include "entity.h"
#include "viewthing.h"
CLASS_DECLARATION( Entity, ViewMaster, NULL );
CLASS_DECLARATION( Entity, Viewthing, "viewthing" );
Event EV_ViewThing_Think( "viewthing_think" );
Event EV_ViewThing_ToggleAnimate( "viewanimate", EV_CHEAT );
Event EV_ViewThing_SetModel( "viewmodel", EV_CHEAT );
Event EV_ViewThing_NextFrame( "viewnext", EV_CHEAT );
Event EV_ViewThing_PrevFrame( "viewprev", EV_CHEAT );
Event EV_ViewThing_NextAnim( "viewnextanim", EV_CHEAT );
Event EV_ViewThing_PrevAnim( "viewprevanim", EV_CHEAT );
Event EV_ViewThing_ScaleUp( "viewscaleup", EV_CHEAT );
Event EV_ViewThing_ScaleDown( "viewscaledown", EV_CHEAT );
Event EV_ViewThing_SetScale( "viewscale", EV_CHEAT );
Event EV_ViewThing_SetYaw( "viewyaw", EV_CHEAT );
Event EV_ViewThing_SetPitch( "viewpitch", EV_CHEAT );
Event EV_ViewThing_SetRoll( "viewroll", EV_CHEAT );
Event EV_ViewThing_SetAngles( "viewangles", EV_CHEAT );
Event EV_ViewThing_Spawn( "viewspawn", EV_CHEAT );
Event EV_ViewThing_Next( "viewthingnext", EV_CHEAT );
Event EV_ViewThing_Prev( "viewthingprev", EV_CHEAT );
Event EV_ViewThing_Attach( "viewattach", EV_CHEAT );
Event EV_ViewThing_Detach( "viewdetach", EV_CHEAT );
Event EV_ViewThing_DetachAll( "viewdetachall", EV_CHEAT );
Event EV_ViewThing_Delete( "viewdelete", EV_CHEAT );
Event EV_ViewThing_BoneGroup( "viewbonegroup", EV_CHEAT );
Event EV_ViewThing_BoneNum( "viewbonenum", EV_CHEAT );
Event EV_ViewThing_BoneAngles( "viewboneangles", EV_CHEAT );
Event EV_ViewThing_SetOrigin( "vieworigin", EV_CHEAT );
Event EV_ViewThing_NextSkin( "viewnextskin", EV_CHEAT );
Event EV_ViewThing_PrevSkin( "viewprevskin", EV_CHEAT );
Event EV_ViewThing_DeleteAll( "viewdeleteall", EV_CHEAT );
Event EV_ViewThing_AutoAnimate( "viewautoanimate", EV_CHEAT );
ResponseDef ViewMaster::Responses[] =
{
{ &EV_ViewThing_Spawn, ( Response )ViewMaster::Spawn },
{ &EV_ViewThing_Next, ( Response )ViewMaster::Next },
{ &EV_ViewThing_Prev, ( Response )ViewMaster::Prev },
{ &EV_ViewThing_SetModel, ( Response )ViewMaster::SetModelEvent },
{ &EV_ViewThing_DeleteAll, ( Response )ViewMaster::DeleteAll },
{ &EV_ViewThing_ToggleAnimate, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_NextFrame, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_PrevFrame, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_NextAnim, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_PrevAnim, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_ScaleUp, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_ScaleDown, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetScale, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetYaw, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetPitch, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetRoll, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetAngles, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_Attach, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_Detach, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_DetachAll, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_Delete, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_BoneGroup, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_BoneNum, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_SetOrigin, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_BoneAngles, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_NextSkin, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_PrevSkin, ( Response )ViewMaster::PassEvent },
{ &EV_ViewThing_AutoAnimate, ( Response )ViewMaster::PassEvent },
{ NULL, NULL }
};
ViewMaster Viewmodel;
ViewMaster::ViewMaster()
{
current_viewthing = 0;
}
void ViewMaster::Next
(
Event *ev
)
{
Viewthing *viewthing;
int next;
next = G_FindClass( current_viewthing, "viewthing" );
if ( next )
{
current_viewthing = next;
viewthing = ( Viewthing * )G_GetEntity( current_viewthing );
gi.dprintf( "current viewthing model %s.\n", viewthing->model.c_str() );
}
else
{
gi.dprintf( "no more viewthings on map.\n" );
}
}
void ViewMaster::Prev
(
Event *ev
)
{
Viewthing *viewthing;
int prev;
int next;
next = 0;
do
{
prev = next;
next = G_FindClass( prev, "viewthing" );
}
while( next != current_viewthing );
if ( prev )
{
current_viewthing = prev;
viewthing = ( Viewthing * )G_GetEntity( current_viewthing );
gi.dprintf( "current viewthing model %s.\n", viewthing->model.c_str() );
}
else
{
gi.dprintf( "no more viewthings on map.\n" );
}
}
void ViewMaster::DeleteAll
(
Event *ev
)
{
Viewthing *viewthing;
int next;
next = 0;
while( next = G_FindClass( next, "viewthing" ) )
{
viewthing = ( Viewthing * )G_GetEntity( next );
viewthing->PostEvent( EV_Remove, 0 );
}
current_viewthing = 0;
}
void ViewMaster::Spawn
(
Event *ev
)
{
Viewthing *viewthing;
const char *mdl;
Vector forward;
Vector right;
Vector up;
Vector delta;
Event *event;
Entity *ent;
mdl = ev->GetString( 1 );
if ( !mdl || !mdl[ 0 ] )
{
ev->Error( "Must specify a model name" );
return;
}
// Check if we have a client
ent = g_edicts[ 1 ].entity;
assert( ent );
if ( !ent )
{
return;
}
// create a new viewthing
viewthing = new Viewthing;
// set the current_viewthing
current_viewthing = viewthing->entnum;
//FIXME FIXME
ent->angles.AngleVectors( &forward, &right, &up );
viewthing->baseorigin = ent->worldorigin;
viewthing->baseorigin += forward * 48;
viewthing->baseorigin += up * 48;
viewthing->setOrigin( viewthing->baseorigin );
viewthing->droptofloor( 256 );
viewthing->baseorigin = viewthing->worldorigin;
delta = ent->worldorigin - viewthing->worldorigin;
delta[ 2 ] = -delta[ 2 ];
viewthing->setAngles( delta.toAngles() );
event = new Event( EV_ViewThing_SetModel );
event->AddString( mdl );
viewthing->ProcessEvent( event );
}
void ViewMaster::SetModelEvent
(
Event *ev
)
{
const char *mdl;
char str[ 128 ];
Event *event;
Viewthing *viewthing;
mdl = ev->GetString( 1 );
if ( !mdl || !mdl[ 0 ] )
{
ev->Error( "Must specify a model name" );
}
if ( !current_viewthing )
{
int next;
// try to find one on the map
next = G_FindClass( current_viewthing, "viewthing" );
if ( next )
current_viewthing = next;
else
ev->Error( "No viewmodel" );
}
viewthing = ( Viewthing * )G_GetEntity( current_viewthing );
// Prepend 'models/' to make things easier
str[ 0 ] = 0;
if ( ( mdl[ 1 ] != ':' ) && strnicmp( mdl, "models", 6 ) )
{
strcpy( str, "models/" );
}
strcat( str, mdl );
event = new Event( EV_ViewThing_SetModel );
event->AddString( str );
viewthing->ProcessEvent( event );
}
void ViewMaster::PassEvent
(
Event *ev
)
{
Viewthing *viewthing;
Event *event;
if ( !current_viewthing )
{
ev->Error( "No viewmodel" );
}
viewthing = ( Viewthing * )G_GetEntity( current_viewthing );
if ( viewthing )
{
event = new Event( ev );
viewthing->ProcessEvent( event );
}
}
ResponseDef Viewthing::Responses[] =
{
{ &EV_ViewThing_Think, ( Response )Viewthing::Think },
{ &EV_LastFrame, ( Response )Viewthing::LastFrameEvent },
{ &EV_ViewThing_ToggleAnimate, ( Response )Viewthing::ToggleAnimateEvent },
{ &EV_ViewThing_SetModel, ( Response )Viewthing::SetModelEvent },
{ &EV_ViewThing_NextFrame, ( Response )Viewthing::NextFrameEvent },
{ &EV_ViewThing_PrevFrame, ( Response )Viewthing::PrevFrameEvent },
{ &EV_ViewThing_NextAnim, ( Response )Viewthing::NextAnimEvent },
{ &EV_ViewThing_PrevAnim, ( Response )Viewthing::PrevAnimEvent },
{ &EV_ViewThing_ScaleUp, ( Response )Viewthing::ScaleUpEvent },
{ &EV_ViewThing_ScaleDown, ( Response )Viewthing::ScaleDownEvent },
{ &EV_ViewThing_SetScale, ( Response )Viewthing::SetScaleEvent },
{ &EV_ViewThing_SetYaw, ( Response )Viewthing::SetYawEvent },
{ &EV_ViewThing_SetPitch, ( Response )Viewthing::SetPitchEvent },
{ &EV_ViewThing_SetRoll, ( Response )Viewthing::SetRollEvent },
{ &EV_ViewThing_SetAngles, ( Response )Viewthing::SetAnglesEvent },
{ &EV_ViewThing_Attach, ( Response )Viewthing::AttachModel },
{ &EV_ViewThing_Detach, ( Response )Viewthing::Delete },
{ &EV_ViewThing_DetachAll, ( Response )Viewthing::DetachAll },
{ &EV_ViewThing_Delete, ( Response )Viewthing::Delete },
{ &EV_ViewThing_BoneGroup, ( Response )Viewthing::BoneGroup },
{ &EV_ViewThing_BoneNum, ( Response )Viewthing::BoneNum },
{ &EV_ViewThing_SetOrigin, ( Response )Viewthing::ChangeOrigin },
{ &EV_ViewThing_BoneAngles, ( Response )Viewthing::ChangeBoneAngles },
{ &EV_ViewThing_NextSkin, ( Response )Viewthing::NextSkinEvent },
{ &EV_ViewThing_PrevSkin, ( Response )Viewthing::PrevSkinEvent },
{ &EV_ViewThing_AutoAnimate, ( Response )Viewthing::AutoAnimateEvent },
{ NULL, NULL }
};
Viewthing::Viewthing
(
void
)
{
animstate = 0;
setSolidType( SOLID_BBOX );
baseorigin = origin;
Viewmodel.current_viewthing = entnum;
PostEvent( EV_ViewThing_Think, FRAMETIME );
}
void Viewthing::Think
(
Event *ev
)
{
if (animstate >= 2)
{
Vector forward;
Vector right;
Vector up;
Vector realmove;
angles.AngleVectors( &forward, &right, &up );
realmove = right * total_delta[1] + up * total_delta[2] + forward * total_delta[0];
setOrigin( baseorigin + realmove );
}
PostEvent( EV_ViewThing_Think, FRAMETIME );
if ( ( animstate > 0 ) && ( Viewmodel.current_viewthing == entnum ) )
{
gi.dprintf( "current frame %d time %.2f\n", edict->s.frame, gi.Frame_Time( edict->s.modelindex, edict->s.anim, edict->s.frame ) );
}
}
void Viewthing::LastFrameEvent
(
Event *ev
)
{
if ( animstate != 3 )
{
total_delta = "0 0 0";
}
}
void Viewthing::ToggleAnimateEvent
(
Event *ev
)
{
animstate = ( animstate + 1 ) % 4;
// reset to a known state
StopAnimating();
switch( animstate )
{
case 0:
total_delta = "0 0 0";
setOrigin( baseorigin );
gi.dprintf( "Animation stopped.\n" );
break;
case 1:
total_delta = "0 0 0";
setOrigin( baseorigin );
StartAnimating();
gi.dprintf( "Animation no motion.\n" );
break;
case 2:
StartAnimating();
gi.dprintf( "Animation with motion and looping.\n" );
break;
case 3:
StartAnimating();
gi.dprintf( "Animation with motion no looping.\n" );
break;
}
}
void Viewthing::SetModelEvent
(
Event *ev
)
{
setModel( ev->GetString( 1 ) );
NextAnim( 0 );
}
void Viewthing::NextFrameEvent
(
Event *ev
)
{
NextFrame( edict->s.frame + 1 );
AnimateFrame();
StopAnimating();
animstate = 0;
gi.dprintf( "current frame %d time %.2f\n", edict->s.frame, gi.Frame_Time( edict->s.modelindex, edict->s.anim, edict->s.frame ) );
}
void Viewthing::PrevFrameEvent
(
Event *ev
)
{
edict->s.frame--;
if ( edict->s.frame < 0 )
{
edict->s.frame = last_frame_in_anim;
}
NextFrame( edict->s.frame );
AnimateFrame();
StopAnimating();
animstate = 0;
gi.dprintf( "current frame %d time %.2f\n", edict->s.frame, gi.Frame_Time( edict->s.modelindex, edict->s.anim, edict->s.frame ) );
}
void Viewthing::NextAnimEvent
(
Event *ev
)
{
int group_num;
StopAnimating();
for( group_num = 0; group_num < edict->s.numgroups ; group_num++ )
{
edict->s.groups[ group_num ] &= ~( MDL_GROUP_NODRAW | MDL_GROUP_SKINOFFSET_BIT0 );
}
NextAnim( edict->s.anim + 1 );
NextFrame( 0 );
AnimateFrame();
StopAnimating();
animstate = 0;
gi.dprintf( "current anim %s\n", gi.Anim_NameForNum( edict->s.modelindex, edict->s.anim ) );
}
void Viewthing::PrevAnimEvent
(
Event *ev
)
{
int group_num;
StopAnimating();
for( group_num = 0; group_num < edict->s.numgroups ; group_num++ )
{
edict->s.groups[ group_num ] &= ~( MDL_GROUP_NODRAW | MDL_GROUP_SKINOFFSET_BIT0 );
}
NextAnim( edict->s.anim - 1 );
NextFrame( 0 );
AnimateFrame();
StopAnimating();
animstate = 0;
gi.dprintf( "current anim %s\n", gi.Anim_NameForNum( edict->s.modelindex, edict->s.anim ) );
}
void Viewthing::ScaleUpEvent
(
Event *ev
)
{
edict->s.scale += 0.01f;
gi.dprintf( "viewscale = %f\n", edict->s.scale );
}
void Viewthing::ScaleDownEvent
(
Event *ev
)
{
edict->s.scale -= 0.01f;
gi.dprintf( "viewscale = %f\n", edict->s.scale );
}
void Viewthing::SetScaleEvent
(
Event *ev
)
{
float s;
if ( ev->NumArgs() )
{
s = ev->GetFloat( 1 );
edict->s.scale = s;
gi.dprintf( "viewscale = %f\n", edict->s.scale );
}
else
{
gi.dprintf( "viewscale = %f\n", edict->s.scale );
}
}
void Viewthing::SetYawEvent
(
Event *ev
)
{
if ( ev->NumArgs() > 0 )
{
angles.setYaw( ev->GetFloat( 1 ) );
setAngles( angles );
}
gi.dprintf( "yaw = %f\n", angles.yaw() );
}
void Viewthing::SetPitchEvent
(
Event *ev
)
{
if ( ev->NumArgs() > 0 )
{
angles.setPitch( ev->GetFloat( 1 ) );
setAngles( angles );
}
gi.dprintf( "pitch = %f\n", angles.pitch() );
}
void Viewthing::SetRollEvent
(
Event *ev
)
{
if ( ev->NumArgs() > 0 )
{
angles.setRoll( ev->GetFloat( 1 ) );
setAngles( angles );
}
gi.dprintf( "roll = %f\n", angles.roll() );
}
void Viewthing::SetAnglesEvent
(
Event *ev
)
{
if ( ev->NumArgs() > 2 )
{
angles.x = ev->GetFloat( 1 );
angles.y = ev->GetFloat( 2 );
angles.z = ev->GetFloat( 3 );
setAngles( angles );
}
gi.dprintf( "angles = %f, %f, %f\n", angles.x, angles.y, angles.z );
}
void Viewthing::AttachModel
(
Event *ev
)
{
int groupindex;
int tri_num;
vec3_t orient;
if ( gi.GetBoneInfo( edict->s.modelindex, ev->GetString( 1 ), &groupindex, &tri_num, orient ) )
{
Viewthing * child;
child = new Viewthing;
//
// attach the child
//
child->setModel( ev->GetString( 2 ) );
child->attach( entnum, groupindex, tri_num, Vector(orient) );
}
else
{
gi.dprintf( "attach failed\n" );
}
}
void Viewthing::Delete
(
Event *ev
)
{
Viewmodel.current_viewthing = 0;
PostEvent( EV_Remove, 0 );
}
void Viewthing::DetachAll
(
Event *ev
)
{
int i;
int num;
num = numchildren;
for (i=0;i<MAX_MODEL_CHILDREN;i++)
{
Entity * ent;
if (!children[i])
continue;
ent = ( Entity * )G_GetEntity( children[i] );
ent->PostEvent( EV_Remove, 0 );
num--;
if (!num)
break;
}
}
void Viewthing::BoneGroup
(
Event *ev
)
{
int s;
if ( ev->NumArgs() )
{
s = ev->GetInteger( 1 );
edict->s.bone.group_num = s;
}
gi.dprintf( "bone_group = %d\n", edict->s.bone.group_num );
}
void Viewthing::BoneNum
(
Event *ev
)
{
int s;
if ( ev->NumArgs() )
{
s = ev->GetInteger( 1 );
edict->s.bone.tri_num = s;
}
gi.dprintf( "bone_num = %d\n", edict->s.bone.tri_num );
}
void Viewthing::ChangeOrigin
(
Event *ev
)
{
if ( ev->NumArgs() )
{
origin.x = ev->GetFloat( 1 );
origin.y = ev->GetFloat( 2 );
origin.z = ev->GetFloat( 3 );
setOrigin( origin );
baseorigin = origin;
}
gi.dprintf( "vieworigin = x%f y%f z%f\n", origin.x, origin.y, origin.z );
}
void Viewthing::ChangeBoneAngles
(
Event *ev
)
{
if ( ev->NumArgs() )
{
edict->s.bone.orientation[0] = ev->GetFloat( 1 );
edict->s.bone.orientation[1] = ev->GetFloat( 2 );
edict->s.bone.orientation[2] = ev->GetFloat( 3 );
}
gi.dprintf( "boneangles = x%f y%f z%f\n", edict->s.bone.orientation[0], edict->s.bone.orientation[1], edict->s.bone.orientation[2] );
}
void Viewthing::NextSkinEvent
(
Event *ev
)
{
edict->s.skinnum = (edict->s.skinnum + 1)%gi.NumSkins( edict->s.modelindex );
gi.dprintf( "current skin %s\n", gi.Skin_NameForNum( edict->s.modelindex, edict->s.skinnum ));
}
void Viewthing::PrevSkinEvent
(
Event *ev
)
{
edict->s.skinnum = (edict->s.skinnum - 1)%gi.NumSkins( edict->s.modelindex );
gi.dprintf( "current skin %s\n", gi.Skin_NameForNum( edict->s.modelindex, edict->s.skinnum ));
}
void Viewthing::AutoAnimateEvent
(
Event *ev
)
{
if ( edict->s.effects & EF_AUTO_ANIMATE )
{
gi.dprintf( "turning off auto animation\n" );
edict->s.effects &= ~EF_AUTO_ANIMATE;
}
else
{
gi.dprintf( "turning on auto animation\n" );
edict->s.effects |= EF_AUTO_ANIMATE;
}
}