2604 lines
72 KiB
C++
2604 lines
72 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /EF2/Code/DLLs/game/viewthing.cpp $
|
|
// $Revision:: 46 $
|
|
// $Author:: Singlis $
|
|
// $Date:: 9/26/03 2:36p $
|
|
//
|
|
// 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 "_pch_cpp.h"
|
|
#include "entity.h"
|
|
#include "viewthing.h"
|
|
#include "player.h"
|
|
#include "q_shared.h"
|
|
#include <qcommon/cm_public.h>
|
|
|
|
// These command vars are used with the viewset and viewlist commands
|
|
cvar_t *g_vt_droptoggle; // treated as a boolean. If true, we drop newly spawned things
|
|
cvar_t *g_vt_setFilename ; // contains the filename of the current .lst file (if any)
|
|
cvar_t *g_vt_modelIndex ; // Index specifying which model in the .lst file we are viewing
|
|
cvar_t *g_vt_numModels ; // Number of total models in the .lst file
|
|
cvar_t *g_vt_height ; // Z Height off 0 that we position spawned things
|
|
cvar_t *g_vt_scale ; // Scale of spawned things
|
|
cvar_t *g_vt_yaw ; // Current yaw value for spawned things
|
|
cvar_t *g_vt_roll ; // Current roll value for spawned things
|
|
cvar_t *g_vt_pitch ; // Current pitch value for spawned things
|
|
cvar_t *g_vt_xtrans ; // Current x translation for current viewthing
|
|
cvar_t *g_vt_ytrans ; // Current y translation for current viewthing
|
|
cvar_t *g_vt_ztrans ; // Current z translation for current viewthing
|
|
cvar_t *g_vt_makestatic ; // Toggle for controlling if spawned objects are "static" (static lighting) or not.
|
|
cvar_t *g_vt_usebox ; // When shooting objects, objects pull away from wall by their bounding box. Defaults true.
|
|
cvar_t *g_vt_viewcount ; // Holds number of spawned viewthings
|
|
cvar_t *g_vt_viewnumber ; // Holds position of current_viewthing amongst all spawned ones
|
|
cvar_t *g_vt_viewrandomize ; // If true (default is false) spawned things are affected by randomization settings (below)
|
|
cvar_t *g_vt_viewsrandomize; // If true randomize scale (default true)
|
|
cvar_t *g_vt_viewzrandomize; // If true randomize rotations about z axis (yaw) (default false)
|
|
cvar_t *g_vt_viewyrandomize; // If true randomize rotations about y axis (pitch) (default false)
|
|
cvar_t *g_vt_viewxrandomize; // If true randomize rotations about x axis (roll) (default false)
|
|
cvar_t *g_vt_viewminrandomize;// Min value for randomizing scale (default is 50%)
|
|
cvar_t *g_vt_viewmaxrandomize;// Max value for randomizing scale (default is 150%)
|
|
cvar_t *g_vt_viewbellrandomize;// Set to true if you want scale randomizatins to be on a bell curve (default true)
|
|
|
|
|
|
Event EV_ViewThing_Think
|
|
(
|
|
"viewthing_think",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Called every frame to process the view thing."
|
|
);
|
|
Event EV_ViewThing_ToggleAnimate
|
|
(
|
|
"viewanimate",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Cycle through the animations modes of the current viewthing\n"
|
|
"No Animation\n"
|
|
"Animation with no motion\n"
|
|
"Animation with looping motion\n"
|
|
"Animation with motion\n"
|
|
);
|
|
Event EV_ViewThing_SetModel
|
|
(
|
|
"viewmodel",
|
|
EV_CHEAT,
|
|
"s",
|
|
"viewthingModel",
|
|
"Set the model of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_NextFrame
|
|
(
|
|
"viewnext",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Advance to the next frame of animation of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_PrevFrame
|
|
(
|
|
"viewprev",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Advance to the previous frame of animation of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_NextAnim
|
|
(
|
|
"viewnextanim",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Advance to the next animation of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_PrevAnim
|
|
(
|
|
"viewprevanim",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Advance to the previous animation of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetFrame
|
|
(
|
|
"viewsetframe",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Set the animation to a specific frame number."
|
|
);
|
|
Event EV_ViewThing_ScaleUp
|
|
(
|
|
"viewscaleup",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Increase the scale of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_ScaleDown
|
|
(
|
|
"viewscaledown",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Decrease the scale of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetScale
|
|
(
|
|
"viewscale",
|
|
EV_CHEAT,
|
|
"f",
|
|
"scale",
|
|
"Set the scale of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetYaw
|
|
(
|
|
"viewyaw",
|
|
EV_CHEAT,
|
|
"f",
|
|
"yaw",
|
|
"Set the yaw of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetPitch
|
|
(
|
|
"viewpitch",
|
|
EV_CHEAT,
|
|
"f",
|
|
"pitch",
|
|
"Set the pitch of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetRoll
|
|
(
|
|
"viewroll",
|
|
EV_CHEAT,
|
|
"f",
|
|
"roll",
|
|
"Set the roll of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetAngles
|
|
(
|
|
"viewangles",
|
|
EV_CHEAT,
|
|
"f[0,360]f[0,360]f[0,360]",
|
|
"pitch yaw roll",
|
|
"Set the angles of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_TranslateX
|
|
(
|
|
"viewxtranslate",
|
|
EV_CHEAT,
|
|
"f",
|
|
"xtrans",
|
|
"Translate current viewthing in x direction"
|
|
);
|
|
Event EV_ViewThing_TranslateY
|
|
(
|
|
"viewytranslate",
|
|
EV_CHEAT,
|
|
"f",
|
|
"ytrans",
|
|
"Translate current viewthing in y direction"
|
|
);
|
|
Event EV_ViewThing_TranslateZ
|
|
(
|
|
"viewztranslate",
|
|
EV_CHEAT,
|
|
"f",
|
|
"ztrans",
|
|
"Translate current viewthing in z direction"
|
|
);
|
|
Event EV_ViewThing_Pull
|
|
(
|
|
"viewthingpull",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Pulls the current viewthing to the camera"
|
|
);
|
|
Event EV_ViewThing_Spawn
|
|
(
|
|
"viewspawn",
|
|
EV_CHEAT,
|
|
"s",
|
|
"model",
|
|
"Create a viewthing with the specified model"
|
|
);
|
|
Event EV_ViewThing_SpawnFromTS
|
|
(
|
|
"viewspawnfromts",
|
|
EV_CHEAT,
|
|
"sS",
|
|
"reloadmodel spawnmodel",
|
|
"Create a viewthing from the model specified by the ToolServer"
|
|
);
|
|
Event EV_ViewThing_Next
|
|
(
|
|
"viewthingnext",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Change the active viewthing to the next viewthing"
|
|
);
|
|
Event EV_ViewThing_Prev
|
|
(
|
|
"viewthingprev",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Change the active viewthing to the previous viewthing"
|
|
);
|
|
Event EV_ViewThing_Attach
|
|
(
|
|
"viewattach",
|
|
EV_CHEAT,
|
|
"ss",
|
|
"tagname model",
|
|
"Attach a model the the specified tagname"
|
|
);
|
|
Event EV_ViewThing_Detach
|
|
(
|
|
"viewdetach",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Detach the current viewthing from its parent"
|
|
);
|
|
Event EV_ViewThing_DetachAll
|
|
(
|
|
"viewdetachall",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Detach all the models attached to the current viewthing"
|
|
);
|
|
Event EV_ViewThing_Delete
|
|
(
|
|
"viewdelete",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Delete the current viewthing"
|
|
);
|
|
Event EV_ViewThing_SetStatic
|
|
(
|
|
"viewsetstatic",
|
|
EV_CHEAT,
|
|
"i",
|
|
"boolean",
|
|
"Makes the current viewthing a static (not dynamically lit) object"
|
|
);
|
|
Event EV_ViewThing_SetOrigin
|
|
(
|
|
"vieworigin",
|
|
EV_CHEAT,
|
|
"fff",
|
|
"x y z",
|
|
"Set the origin of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_DeleteAll
|
|
(
|
|
"viewdeleteall",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Delete all viewthings"
|
|
);
|
|
Event EV_ViewThing_LastFrame
|
|
(
|
|
"viewlastframe",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Called when the view things last animation frame is displayed."
|
|
);
|
|
Event EV_ViewThing_SaveOffSurfaces
|
|
(
|
|
"viewsavesurfaces",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Called after the model is spawned to save off the models original surfaces."
|
|
);
|
|
Event EV_ViewThing_PrintTime
|
|
(
|
|
"_viewthing_printtime",
|
|
EV_CODEONLY,
|
|
NULL,
|
|
NULL,
|
|
"Prints out the current level.time."
|
|
);
|
|
Event EV_ViewThing_SetAnim
|
|
(
|
|
"viewsetanim",
|
|
EV_CHEAT,
|
|
"f",
|
|
"animNum",
|
|
"Set the animation absolutely based off a floating point value"
|
|
);
|
|
Event EV_ViewThing_NextMorph
|
|
(
|
|
"viewnextmorph",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Goes to the next morph for this model"
|
|
);
|
|
Event EV_ViewThing_PrevMorph
|
|
(
|
|
"viewprevmorph",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Goes to the previous morph for this model"
|
|
);
|
|
Event EV_ViewThing_Morph
|
|
(
|
|
"viewmorph",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Morphs the current morph"
|
|
);
|
|
Event EV_ViewThing_Unmorph
|
|
(
|
|
"viewunmorph",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Unmorphs the current morph"
|
|
);
|
|
Event EV_ViewSet_Load
|
|
(
|
|
"viewsetload",
|
|
EV_CHEAT,
|
|
"s",
|
|
"filename",
|
|
"Loads the specified viewset"
|
|
);
|
|
Event EV_ViewSet_Save
|
|
(
|
|
"viewsetsave",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Saves names and positions of currently spawned things data to disk"
|
|
);
|
|
Event EV_ViewThing_Copy
|
|
(
|
|
"viewcopy",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Copies the current viewthing"
|
|
);
|
|
Event EV_ViewThing_Shoot
|
|
(
|
|
"viewshoot",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Shoots current viewthing ahead and sticks it on the wall"
|
|
);
|
|
Event EV_ViewList_List
|
|
(
|
|
"viewlistlist",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"List all TIKIs in the current .lst set"
|
|
);
|
|
Event EV_ViewList_NextInSet
|
|
(
|
|
"viewlistnext",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Delete current viewthing and load next view thing in view list"
|
|
);
|
|
Event EV_ViewList_PrevInSet
|
|
(
|
|
"viewlistprev",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Delete current viewthing and load prev view thing in view list"
|
|
);
|
|
Event EV_ViewList_LiftModel
|
|
(
|
|
"viewlistliftmodel",
|
|
EV_CHEAT,
|
|
"f",
|
|
"z",
|
|
"Raise the origin (z) by specified amount"
|
|
);
|
|
Event EV_ViewList_ToggleDrop
|
|
(
|
|
"viewlisttoggledrop",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Toggle whether objects are dropped upon spawning"
|
|
);
|
|
Event EV_ViewList_Jump
|
|
(
|
|
"viewlistjump",
|
|
EV_CHEAT,
|
|
"i",
|
|
"modelindex",
|
|
"Jumps to a specific model in a view set (.lst file) of models"
|
|
);
|
|
Event EV_ViewThing_ResetOrigin
|
|
(
|
|
"viewresetorigin",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Sets the origin of current viewspawn to its current origin"
|
|
);
|
|
Event EV_ViewThing_XTrans
|
|
(
|
|
"viewtransx",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"translate current viewspawn in x direction by specified amount"
|
|
);
|
|
Event EV_ViewThing_YTrans
|
|
(
|
|
"viewtransy",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"translate current viewspawn in y direction by specified amount"
|
|
);
|
|
Event EV_ViewThing_ZTrans
|
|
(
|
|
"viewtransz",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"translate current viewspawn in z direction by specified amount"
|
|
);
|
|
Event EV_ViewThing_Offset
|
|
(
|
|
"viewoffset",
|
|
EV_CHEAT,
|
|
"fff",
|
|
"x y z",
|
|
"Offsets the origin of the current viewthing"
|
|
);
|
|
Event EV_ViewThing_ChangeRoll
|
|
(
|
|
"viewchangeroll",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"rotate current viewspawn around x axis by specified amount"
|
|
);
|
|
Event EV_ViewThing_ChangePitch
|
|
(
|
|
"viewchangepitch",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"rotate current viewspawn around y axis by specified amount"
|
|
);
|
|
Event EV_ViewThing_ChangeYaw
|
|
(
|
|
"viewchangeyaw",
|
|
EV_CHEAT,
|
|
"i",
|
|
"offsetamount",
|
|
"rotate current viewspawn around z axis by specified amount"
|
|
);
|
|
Event EV_ViewThing_Flash
|
|
(
|
|
"viewflash",
|
|
EV_CHEAT,
|
|
NULL,
|
|
NULL,
|
|
"Flashes the currently select viewthing"
|
|
);
|
|
|
|
CLASS_DECLARATION( Listener, ViewMaster, NULL )
|
|
{
|
|
{ &EV_ViewThing_Spawn, &ViewMaster::Spawn },
|
|
{ &EV_ViewThing_SpawnFromTS, &ViewMaster::SpawnFromTS },
|
|
{ &EV_ViewThing_Next, &ViewMaster::Next },
|
|
{ &EV_ViewThing_Prev, &ViewMaster::Prev },
|
|
{ &EV_ViewThing_SetModel, &ViewMaster::SetModelEvent },
|
|
{ &EV_ViewThing_DeleteAll, &ViewMaster::DeleteAll },
|
|
{ &EV_ViewThing_ToggleAnimate, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_NextFrame, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_PrevFrame, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_NextAnim, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_PrevAnim, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_ScaleUp, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_ScaleDown, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetScale, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetYaw, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetPitch, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetRoll, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetAngles, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_Attach, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_Detach, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_DetachAll, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetStatic, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetOrigin, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetAnim, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_NextMorph, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_PrevMorph, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_Morph, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_Unmorph, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_ChangeRoll, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_ChangePitch, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_ChangeYaw, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_Flash, &ViewMaster::PassEvent },
|
|
{ &EV_ViewThing_SetFrame, &ViewMaster::PassEvent },
|
|
{ &EV_ViewSet_Load, &ViewMaster::LoadSet },
|
|
{ &EV_ViewSet_Save, &ViewMaster::Save },
|
|
{ &EV_ViewThing_Copy, &ViewMaster::Copy },
|
|
{ &EV_ViewThing_Shoot, &ViewMaster::Shoot },
|
|
{ &EV_ViewThing_Delete, &ViewMaster::Delete },
|
|
{ &EV_ViewThing_TranslateX, &ViewMaster::SetXTranslation },
|
|
{ &EV_ViewThing_TranslateY, &ViewMaster::SetYTranslation },
|
|
{ &EV_ViewThing_TranslateZ, &ViewMaster::SetZTranslation },
|
|
{ &EV_ViewList_PrevInSet, &ViewMaster::PrevModelInSet },
|
|
{ &EV_ViewList_NextInSet, &ViewMaster::NextModelInSet },
|
|
{ &EV_ViewList_LiftModel, &ViewMaster::SetZTranslation },
|
|
{ &EV_ViewList_ToggleDrop, &ViewMaster::ToggleDrop },
|
|
{ &EV_ViewList_Jump, &ViewMaster::JumpToModel },
|
|
{ &EV_ViewThing_Pull, &ViewMaster::PullToCamera },
|
|
{ &EV_ViewThing_ResetOrigin, &ViewMaster::ResetOrigin },
|
|
{ &EV_ViewThing_XTrans, &ViewMaster::XTranslate },
|
|
{ &EV_ViewThing_YTrans, &ViewMaster::YTranslate },
|
|
{ &EV_ViewThing_ZTrans, &ViewMaster::ZTranslate },
|
|
{ &EV_ViewThing_Offset, &ViewMaster::Offset },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
ViewMaster Viewmodel;
|
|
|
|
ViewMaster::ViewMaster()
|
|
{
|
|
current_viewthing = NULL;
|
|
_spawnAtLastItemsOrigin = false ;
|
|
_currentSetIdx = 0 ;
|
|
_numberOfSets = 0 ;
|
|
_numberOfModelsInSet = 0 ;
|
|
}
|
|
|
|
ViewMaster::~ViewMaster()
|
|
{
|
|
_setNamesArray.FreeObjectList();
|
|
_modelNamesArray.FreeObjectList();
|
|
}
|
|
|
|
void ViewMaster::Init( void )
|
|
{
|
|
gi.AddCommand( "viewanimate" );
|
|
gi.AddCommand( "viewmodel" );
|
|
gi.AddCommand( "viewnext" );
|
|
gi.AddCommand( "viewprev" );
|
|
gi.AddCommand( "viewnextanim" );
|
|
gi.AddCommand( "viewprevanim" );
|
|
gi.AddCommand( "viewscaleup" );
|
|
gi.AddCommand( "viewscaledown" );
|
|
gi.AddCommand( "viewscale" );
|
|
gi.AddCommand( "viewyaw" );
|
|
gi.AddCommand( "viewpitch" );
|
|
gi.AddCommand( "viewroll" );
|
|
gi.AddCommand( "viewangles" );
|
|
gi.AddCommand( "viewxtranslate" );
|
|
gi.AddCommand( "viewytranslate" );
|
|
gi.AddCommand( "viewztranslate" );
|
|
gi.AddCommand( "viewoffset" );
|
|
gi.AddCommand( "viewspawn" );
|
|
gi.AddCommand( "viewspawnfromts");
|
|
gi.AddCommand( "viewthingnext" );
|
|
gi.AddCommand( "viewthingprev" );
|
|
gi.AddCommand( "viewthingpull" );
|
|
gi.AddCommand( "viewattach" );
|
|
gi.AddCommand( "viewdetach" );
|
|
gi.AddCommand( "viewdetachall" );
|
|
gi.AddCommand( "viewdelete" );
|
|
gi.AddCommand( "viewsetstatic" );
|
|
gi.AddCommand( "vieworiginlift" );
|
|
gi.AddCommand( "vieworigin" );
|
|
gi.AddCommand( "viewdeleteall" );
|
|
gi.AddCommand( "viewsetanim" );
|
|
gi.AddCommand( "viewsetload" );
|
|
gi.AddCommand( "viewsetnext" );
|
|
gi.AddCommand( "viewsetprev" );
|
|
gi.AddCommand( "viewsetsave" );
|
|
gi.AddCommand( "viewcopy" );
|
|
gi.AddCommand( "viewlistlist" );
|
|
gi.AddCommand( "viewlistnext" );
|
|
gi.AddCommand( "viewlistprev" );
|
|
gi.AddCommand( "viewlistliftmodel" );
|
|
gi.AddCommand( "viewlisttoggledrop" );
|
|
gi.AddCommand( "viewlistjump" );
|
|
gi.AddCommand( "viewresetorigin" );
|
|
gi.AddCommand( "viewtransx" );
|
|
gi.AddCommand( "viewtransy" );
|
|
gi.AddCommand( "viewtransz" );
|
|
gi.AddCommand( "viewflash" );
|
|
gi.AddCommand( "viewsetframe" );
|
|
|
|
g_vt_droptoggle = gi.cvar( "g_vt_droptoggle", "1", 0 );
|
|
g_vt_setFilename = gi.cvar( "g_vt_setFilename", "", 0 );
|
|
g_vt_modelIndex = gi.cvar( "g_vt_modelIndex", "0", 0 );
|
|
g_vt_height = gi.cvar( "g_vt_height", "0", 0 );
|
|
g_vt_makestatic = gi.cvar( "g_vt_makestatic", "1", 0 );
|
|
g_vt_scale = gi.cvar( "g_vt_scale", "1.0", 0 );
|
|
g_vt_numModels = gi.cvar( "g_vt_numModels", "0", 0 );
|
|
g_vt_yaw = gi.cvar( "g_vt_yaw", "0.0", 0 );
|
|
g_vt_pitch = gi.cvar( "g_vt_pitch", "0.0", 0 );
|
|
g_vt_roll = gi.cvar( "g_vt_roll", "0.0", 0 );
|
|
g_vt_xtrans = gi.cvar( "g_vt_xtrans", "0.0", 0 );
|
|
g_vt_ytrans = gi.cvar( "g_vt_ytrans", "0.0", 0 );
|
|
g_vt_ztrans = gi.cvar( "g_vt_ztrans", "0.0", 0 );
|
|
g_vt_usebox = gi.cvar( "g_vt_usebox", "1", 0 );
|
|
g_vt_viewnumber = gi.cvar( "g_vt_viewnumber", "0", 0 );
|
|
g_vt_viewcount = gi.cvar( "g_vt_viewcount", "0", 0 );
|
|
g_vt_viewrandomize = gi.cvar( "g_vt_viewrandomize", "0", 0 );
|
|
g_vt_viewsrandomize = gi.cvar( "g_vt_viewsrandomize", "1", 0 );
|
|
g_vt_viewzrandomize = gi.cvar( "g_vt_viewzrandomize", "1", 0 );
|
|
g_vt_viewyrandomize = gi.cvar( "g_vt_viewyrandomize", "0", 0 );
|
|
g_vt_viewxrandomize = gi.cvar( "g_vt_viewxrandomize", "0", 0 );
|
|
g_vt_viewminrandomize = gi.cvar( "g_vt_viewminrandomize", "25", 0 );
|
|
g_vt_viewmaxrandomize = gi.cvar( "g_vt_viewmaxrandomize", "175", 0 );
|
|
g_vt_viewbellrandomize = gi.cvar( "g_vt_viewminrandomize", "1", 0 );
|
|
}
|
|
|
|
void ViewMaster::Save( Event *ev )
|
|
{
|
|
// saves currently spawned things to disk
|
|
str buf;
|
|
str filename;
|
|
int count = 1 ;
|
|
|
|
// get the name of the sound file from the world
|
|
filename = "maps/";
|
|
filename += level.mapname;
|
|
for(int i = filename.length() - 1; i >= 0; i-- )
|
|
{
|
|
if ( filename[ i ] == '.' )
|
|
{
|
|
filename[ i ] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
filename += "_ents.map";
|
|
gi.cvar_set("g_vt_savefile", filename.c_str());
|
|
gi.Printf( "Saving spawned things to '%s'...\n", filename.c_str() );
|
|
|
|
buf = "";
|
|
buf += va( "//\n" );
|
|
buf += va( "// Viewspawned entities file \"%s\".\n", filename.c_str());
|
|
buf += va( "//\n" );
|
|
|
|
Viewthing *viewthingPtr = 0 ;
|
|
Entity *entityPtr = 0 ;
|
|
entityPtr = G_FindClass( entityPtr, "viewthing" );
|
|
|
|
while (entityPtr != 0)
|
|
{
|
|
viewthingPtr = (Viewthing*)entityPtr;
|
|
|
|
str modelName = viewthingPtr->model ;
|
|
char* strPtr = (char*)modelName.c_str();
|
|
char* endPtr = strPtr + (strlen(strPtr) - 1) ;
|
|
bool found = false ;
|
|
|
|
for (int idx=strlen(strPtr); idx > 0; idx++)
|
|
{
|
|
if (*endPtr == '/')
|
|
{
|
|
endPtr++ ;
|
|
found = true ;
|
|
break ;
|
|
}
|
|
endPtr-- ;
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
strPtr = endPtr ;
|
|
}
|
|
|
|
buf += va( "// Entity %d\n", count);
|
|
buf += va( "{\n");
|
|
buf += va( "\"make_static\" \"%d\"\n", viewthingPtr->_static);
|
|
buf += va( "\"classname\" \"FROM_TIKI\"\n" );
|
|
buf += va( "\"model\" \"%s\"\n", strPtr);
|
|
buf += va( "\"scale\" \"%f\"\n", viewthingPtr->edict->s.scale);
|
|
buf += va( "\"origin\" \"%.2f %.2f %.2f\"\n", viewthingPtr->origin.x, viewthingPtr->origin.y, viewthingPtr->origin.z );
|
|
buf += va( "\"angles\" \"%.2f %.2f %.2f\"\n", viewthingPtr->angles.x, viewthingPtr->angles.y, viewthingPtr->angles.z );
|
|
buf += va( "\"spawnflags\" \"1\"\n");
|
|
buf += va( "}\n" );
|
|
|
|
entityPtr = G_FindClass( entityPtr, "viewthing");
|
|
count++ ;
|
|
}
|
|
gi.FS_WriteFile( filename.c_str(), buf.c_str(), buf.length() + 1 );
|
|
gi.Printf( "Done.\n" );
|
|
}
|
|
|
|
void ViewMaster::LoadSet( Event *ev )
|
|
{
|
|
// If we have stuff loaded, delete it all
|
|
if (_numberOfModelsInSet || _numberOfSets)
|
|
{
|
|
gi.cvar_set( "viewsetname", va( " ") );
|
|
gi.cvar_set( "viewlistmodelname", va( " ") );
|
|
gi.cvar_set( "g_vt_modelIndex", "0");
|
|
gi.cvar_set( "g_vt_setFilename", "");
|
|
|
|
_currentSetIdx = 0 ;
|
|
_numberOfSets = 0 ;
|
|
_numberOfModelsInSet = 0 ;
|
|
_setNamesArray.FreeObjectList();
|
|
_modelNamesArray.FreeObjectList();
|
|
}
|
|
|
|
str filename = ev->GetString(1);
|
|
_setNamesArray.AddObject(filename);
|
|
_numberOfSets++ ;
|
|
|
|
// If we loaded any tiki filenames, display the first one
|
|
if (_numberOfSets)
|
|
{
|
|
_currentSetIdx = 1 ;
|
|
//str setFilename = _setNamesArray.ObjectAt(_currentSetIdx);
|
|
LoadModelsInSet(_setNamesArray.ObjectAt(_currentSetIdx));
|
|
}
|
|
}
|
|
|
|
|
|
void ViewMaster::LoadModelsInSet( const str &setFileName )
|
|
{
|
|
char *buffer;
|
|
char *buf;
|
|
char com_token[MAX_STRING_CHARS];
|
|
|
|
if (_numberOfModelsInSet)
|
|
{
|
|
gi.cvar_set( "viewlistmodelname", va( " ") );
|
|
gi.cvar_set( "g_vt_modelIndex", "0");
|
|
_modelNamesArray.FreeObjectList();
|
|
_numberOfModelsInSet = 0 ;
|
|
}
|
|
|
|
// Read the viewlist.txt file. This file contains newline seperated list of .tik models
|
|
if ( gi.FS_ReadFile( setFileName, ( void ** )&buf, true ) != -1 )
|
|
{
|
|
buffer = buf;
|
|
while ( 1 )
|
|
{
|
|
// Pull out a token
|
|
strcpy( com_token, COM_ParseExt( &buffer, true ) );
|
|
|
|
// Quit when no more tokens
|
|
if (!com_token[0])
|
|
break;
|
|
|
|
// Check for single comment lines
|
|
if ((com_token[0] != '#')) { // # is a single line comment
|
|
const char *relative_pathname = NULL;
|
|
|
|
str modelName = "models/" ;
|
|
|
|
relative_pathname = strstr( com_token, "models/" );
|
|
|
|
if ( !relative_pathname )
|
|
relative_pathname = strstr( com_token, "models\\" );
|
|
|
|
if ( relative_pathname )
|
|
{
|
|
relative_pathname += strlen( "models/" );
|
|
modelName += relative_pathname;
|
|
}
|
|
else
|
|
{
|
|
modelName += com_token;
|
|
}
|
|
|
|
_modelNamesArray.AddObject(modelName);
|
|
_numberOfModelsInSet++ ;
|
|
}
|
|
|
|
// Read in the rest of the line
|
|
while( 1 )
|
|
{
|
|
strcpy( com_token, COM_ParseExt( &buffer, false ) );
|
|
if (!com_token[0])
|
|
break;
|
|
}
|
|
}
|
|
gi.FS_FreeFile( buf );
|
|
|
|
// If we loaded any tiki filenames, display the first one
|
|
if (_numberOfModelsInSet)
|
|
{
|
|
gi.cvar_set( "g_vt_modelIndex", "1");
|
|
DisplayCurrentModelInSet(false) ;
|
|
}
|
|
|
|
str setName = _setNamesArray.ObjectAt(_currentSetIdx);
|
|
gi.cvar_set( "viewsetname", va( "%s", setName.c_str()) );
|
|
gi.cvar_set( "g_vt_numModels", va( "%d", _numberOfModelsInSet) );
|
|
}
|
|
}
|
|
|
|
void ViewMaster::DisplayCurrentModelInSet( bool spawnAtLastOrigin )
|
|
{
|
|
if ( (g_vt_modelIndex->integer <= 0) || (g_vt_modelIndex->integer > _numberOfModelsInSet) )
|
|
{
|
|
gi.cvar_set( "viewlistmodelname", " " );
|
|
gi.Printf( " No models in set or position out of range\n");
|
|
return ;
|
|
}
|
|
|
|
|
|
// Get the string name of the view item
|
|
str modelName = _modelNamesArray.ObjectAt(g_vt_modelIndex->integer);
|
|
|
|
// Create a new spawn event with item name to send to Spawn function
|
|
Event* spawnEvent = new Event( EV_ViewThing_Spawn);
|
|
spawnEvent->AddString(modelName);
|
|
_spawnAtLastItemsOrigin = spawnAtLastOrigin ;
|
|
Spawn(spawnEvent);
|
|
_spawnAtLastItemsOrigin = false ;
|
|
delete spawnEvent ;
|
|
spawnEvent = 0 ;
|
|
|
|
gi.cvar_set( "viewlistnumitems", va( "%d", _numberOfModelsInSet ) );
|
|
gi.cvar_set( "viewlistmodelname", modelName.c_str() );
|
|
gi.cvar_set( "g_vt_scale", "1.0");
|
|
gi.cvar_set( "g_vt_height", "0" );
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Copy
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Event function to spawn a duplicate of the current
|
|
// viewthing at the spot occupied by the player.
|
|
//
|
|
// The object should be a true copy, including rotation
|
|
// and scaling. But currently isn't. FIXME
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Copy( Event * )
|
|
{
|
|
DisplayCurrentModelInSet(false);
|
|
_updateViewthingCounts();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Shoot
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Event function to spawn a duplicate of the current
|
|
// viewthing at the spot aimed by the player. The new
|
|
// viewthing is not copied in scale or rotation.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Shoot( Event *ev )
|
|
{
|
|
int idx = g_vt_modelIndex->integer ;
|
|
if ( (idx <= 0) || (idx > _modelNamesArray.NumObjects()) ) return ;
|
|
|
|
Vector forward ;
|
|
Vector right ;
|
|
Vector up ;
|
|
Vector view ;
|
|
Vector start;
|
|
Vector end;
|
|
Vector mins = vec_zero ;
|
|
Vector maxs = vec_zero ;
|
|
trace_t trace;
|
|
|
|
// Check if we have a client
|
|
Player* player = (Player*)g_entities[ 0 ].entity;
|
|
if ( !player ) return;
|
|
|
|
Viewthing* viewthing = 0 ;
|
|
if (current_viewthing && g_vt_usebox->integer)
|
|
{
|
|
viewthing = (Viewthing*) ( (Entity*)current_viewthing);
|
|
mins = viewthing->mins ;
|
|
maxs = viewthing->maxs ;
|
|
}
|
|
|
|
view = player->GetVAngles();
|
|
AngleVectors( view, forward, right, up );
|
|
start = player->origin ;
|
|
start.z += player->viewheight ;
|
|
end = start + ( forward * 10000.0f ) ;
|
|
|
|
trace = G_FullTrace( start, mins, maxs, end, player, MASK_SHOT, false, "ViewMaster::shoot" );
|
|
if ( ( trace.fraction == 1.0f ) || trace.allsolid || !trace.ent )
|
|
{
|
|
return ;
|
|
}
|
|
|
|
if ( g_showbullettrace->integer )
|
|
{
|
|
G_DebugLine( start, end, 1.0f, 1.0f, 1.0f, 1.0f );
|
|
}
|
|
|
|
Vector pos = Vector( trace.endpos ) + ( Vector( trace.plane.normal ) * 0.2f );
|
|
|
|
str modelName(_modelNamesArray.ObjectAt(g_vt_modelIndex->integer));
|
|
spawnAtPosition(modelName, pos);
|
|
|
|
if (current_viewthing)
|
|
{
|
|
Event* yawEvent = new Event(EV_ViewThing_SetYaw);
|
|
viewthing = (Viewthing*) ( (Entity*)current_viewthing);
|
|
Vector n(trace.plane.normal);
|
|
float yaw = n.toYaw();
|
|
yawEvent->AddFloat(yaw);
|
|
viewthing->SetYawEvent(yawEvent);
|
|
delete yawEvent ;
|
|
yawEvent = 0 ;
|
|
|
|
if (g_vt_viewrandomize->integer)
|
|
{
|
|
_randomizeViewthing(viewthing);
|
|
}
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: NextModelInSet
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Event function to switch current_viewthing to the
|
|
// next model in the set (if any). This will switch
|
|
// the current tiki model to be the next tiki model in
|
|
// the loaded .lst file. It does not change the number
|
|
// of total viewthings in the world. Wraps when at
|
|
// end of list.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::NextModelInSet( Event * )
|
|
{
|
|
if (!_numberOfModelsInSet)
|
|
{
|
|
gi.Printf(" No current set\n");
|
|
return ;
|
|
}
|
|
|
|
// Increment on to next model
|
|
int nextIndex = ( g_vt_modelIndex->integer >= _numberOfModelsInSet) ? 1 : (g_vt_modelIndex->integer + 1 );
|
|
gi.cvar_set( "g_vt_modelIndex", va( "%d", nextIndex ) );
|
|
DeleteCurrentViewthing();
|
|
DisplayCurrentModelInSet();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: PrevModelInSet
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Event function to switch current_viewthing to the
|
|
// prev model in the set (if any). This will switch
|
|
// the current tiki model to be the prev tiki model in
|
|
// the loaded .lst file. It does not change the number
|
|
// of total viewthings in the world. Wraps when at
|
|
// start of list.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::PrevModelInSet( Event *ev )
|
|
{
|
|
if (!_numberOfModelsInSet)
|
|
{
|
|
gi.Printf(" No models in current set\n");
|
|
return ;
|
|
}
|
|
|
|
// Increment on to next model
|
|
int nextIndex = ( g_vt_modelIndex->integer <= 1) ? _numberOfModelsInSet : ( g_vt_modelIndex->integer - 1 );
|
|
gi.cvar_set( "g_vt_modelIndex", va( "%d", nextIndex ) );
|
|
DeleteCurrentViewthing();
|
|
DisplayCurrentModelInSet() ;
|
|
}
|
|
|
|
//================================================================
|
|
// Name: JumpToModel
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Explicity function to jump to the tiki specified
|
|
// by number out of the total list of tiki's in the
|
|
// load .lst file. This enables random access thru
|
|
// the .lst instead of one at a time.
|
|
//
|
|
// Parameters: Event* -- first argument is position to jump to
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::JumpToModel( Event *ev )
|
|
{
|
|
int nextIndex = ev->GetInteger(1);
|
|
if ((nextIndex < 1) || (nextIndex > _numberOfModelsInSet))
|
|
{
|
|
gi.Printf(" Illegal index for model in viewset list\n");
|
|
return ;
|
|
}
|
|
|
|
gi.cvar_set( "g_vt_modelIndex", va( "%d", nextIndex ) );
|
|
DeleteCurrentViewthing();
|
|
DisplayCurrentModelInSet();
|
|
}
|
|
|
|
void ViewMaster::SetXTranslation( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
float y = viewthing->origin.y ;
|
|
float z = viewthing->origin.z ;
|
|
originEvent->AddFloat(_lastBaseOrigin.x + ev->GetFloat(1));
|
|
originEvent->AddFloat(y);
|
|
originEvent->AddFloat(z);
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
gi.cvar_set( "g_vt_xtrans", va("%0.2f", ev->GetFloat(1)) );
|
|
}
|
|
|
|
void ViewMaster::XTranslate( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
originEvent->AddFloat(viewthing->origin.x + ev->GetFloat(1));
|
|
originEvent->AddFloat(viewthing->origin.y);
|
|
originEvent->AddFloat(viewthing->origin.z);
|
|
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
_resetOrigin();
|
|
}
|
|
|
|
void ViewMaster::SetYTranslation( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
float x = viewthing->origin.x ;
|
|
float z = viewthing->origin.z ;
|
|
originEvent->AddFloat(x);
|
|
originEvent->AddFloat(_lastBaseOrigin.y + ev->GetFloat(1));
|
|
originEvent->AddFloat(z);
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
gi.cvar_set( "g_vt_ytrans", va("%0.2f", ev->GetFloat(1)) );
|
|
}
|
|
|
|
void ViewMaster::YTranslate( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
originEvent->AddFloat(viewthing->origin.x);
|
|
originEvent->AddFloat(viewthing->origin.y + ev->GetFloat(1));
|
|
originEvent->AddFloat(viewthing->origin.z);
|
|
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
_resetOrigin();
|
|
}
|
|
|
|
void ViewMaster::SetZTranslation( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
float x = viewthing->origin.x ;
|
|
float y = viewthing->origin.y ;
|
|
originEvent->AddFloat(x);
|
|
originEvent->AddFloat(y);
|
|
originEvent->AddFloat(_lastBaseOrigin.z + ev->GetFloat(1));
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
gi.cvar_set( "g_vt_ztrans", va("%0.2f", ev->GetFloat(1)) );
|
|
}
|
|
|
|
void ViewMaster::ZTranslate( Event *ev )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
Event *originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
originEvent->AddFloat(viewthing->origin.x);
|
|
originEvent->AddFloat(viewthing->origin.y);
|
|
originEvent->AddFloat(viewthing->origin.z + ev->GetFloat(1));
|
|
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
_resetOrigin();
|
|
}
|
|
|
|
void ViewMaster::Offset( Event *ev )
|
|
{
|
|
Viewthing *viewthing;
|
|
Event *new_event;
|
|
|
|
if ( !current_viewthing )
|
|
return;
|
|
|
|
viewthing = ( Viewthing * )( Entity * )current_viewthing;
|
|
|
|
new_event = new Event( EV_ViewThing_SetOrigin );
|
|
|
|
new_event->AddFloat( viewthing->origin.x + ev->GetFloat( 1 ) );
|
|
new_event->AddFloat( viewthing->origin.y + ev->GetFloat( 2 ) );
|
|
new_event->AddFloat( viewthing->origin.z + ev->GetFloat( 3 ) );
|
|
|
|
viewthing->ProcessEvent( new_event );
|
|
|
|
_resetOrigin();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: ResetOrigin
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Forces the _lastBaseOrigin to be the origin of the
|
|
// current_viewthing (if any). Calls _resetOrigin to
|
|
// do the work.
|
|
//
|
|
// This is useful because models can be translated off
|
|
// of _lastBaseOrigin and reset to it. This enables
|
|
// the _lastBaseOrigin to move to where ever the viewthing
|
|
// has been translated too so further relative movements are
|
|
// relative to this new position.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::ResetOrigin( Event* )
|
|
{
|
|
_resetOrigin();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: PullToCamera
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Moves the current_viewthing (if any) to the current
|
|
// player's (client[0]) position. Does not drop the
|
|
// object but instead explicitly calls _setToPosition
|
|
// to force the origin of the current_viewthing to be
|
|
// at player's positionn.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::PullToCamera( Event* )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
// Check if we have a client
|
|
Entity* clientEntity = g_entities[ 0 ].entity;
|
|
if (!clientEntity) return ;
|
|
|
|
// Store this new camera position as being where items should spawn here on out
|
|
_lastBaseOrigin = clientEntity->origin ;
|
|
_setToPosition(clientEntity->origin);
|
|
}
|
|
|
|
//================================================================
|
|
// Name: ToggleDrop
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Toggles the g_vt_droptoggle cvar. When the
|
|
// cvar is true, objects are dropped upon spawning.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::ToggleDrop( Event * )
|
|
{
|
|
if (g_vt_droptoggle->integer)
|
|
{
|
|
gi.cvar_set("g_vt_droptoggle", "0");
|
|
}
|
|
else
|
|
{
|
|
gi.cvar_set("g_vt_droptoggle", "1");
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Next
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Takes an event and moves to next spawned viewthing
|
|
// if there is one. Does not change current_viewthing
|
|
// if there isn't a next viewthing.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Next( Event * )
|
|
{
|
|
_selectNext();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Prev
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Responds to an event and moves to previous spawned
|
|
// viewthing if there is one. Does not change current_viewthing
|
|
// if there isn't a previous viewthing.
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Prev( Event * )
|
|
{
|
|
_selectPrevious();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: DeleteCurrentViewthing
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Support function that simply sends a EV_Remove event
|
|
// to the current viewthing if there is one. This will
|
|
// delete the current viewthing.
|
|
//
|
|
// Does not modify current_viewthing nor the count of
|
|
// viewthings because it is expected that the caller
|
|
// handles this.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::DeleteCurrentViewthing()
|
|
{
|
|
if (current_viewthing)
|
|
{
|
|
// delete all existing models
|
|
Viewthing *viewthing = (Viewthing*)( (Entity*) current_viewthing);
|
|
viewthing->PostEvent( EV_Remove, 0.0f );
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Delete
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Deletes the current_viewthing if there is one. Attempts
|
|
// to set the current_viewthing to the previous one in the
|
|
// list of viewthings. If it cannot do that, it sets it
|
|
// to the next one. If it cannot do that, it sets current_viewthing
|
|
// to 0 (NULL).
|
|
//
|
|
// Parameters: Event* -- Not used
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Delete( Event * )
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
// Save off the one to delete
|
|
Viewthing *viewthing = (Viewthing*)( (Entity*) current_viewthing);
|
|
|
|
_selectPrevious(); // Try and select previous
|
|
|
|
if (current_viewthing == viewthing) // If same as one we are deleting, there wasn't a previous
|
|
{
|
|
_selectNext(); // Try and select next
|
|
}
|
|
|
|
if (current_viewthing == viewthing) // If same as one we are deleting, there wasn't a next
|
|
{
|
|
current_viewthing = 0 ; // set it to 0
|
|
}
|
|
|
|
// Delete the one we saved off
|
|
viewthing->PostEvent( EV_Remove, 0.0f );
|
|
_updateViewthingCounts(-1); // we pass -1 here because there will be one less viewthing but it hasn't actually been deleted yet
|
|
}
|
|
|
|
//================================================================
|
|
// Name: DeleteAll
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Deletes all viewspawn things currently in memory.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::DeleteAll( Event * )
|
|
{
|
|
Entity *next;
|
|
|
|
for( next = G_FindClass( NULL, "viewthing" ); next != NULL; next = G_FindClass( next, "viewthing" ) )
|
|
{
|
|
next->PostEvent( EV_Remove, 0.0f );
|
|
}
|
|
|
|
current_viewthing = NULL;
|
|
}
|
|
|
|
//================================================================
|
|
// Name: spawnAtPosition
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Spawns the specified tiki model at the specified
|
|
// position. The current_viewthing will point to this
|
|
// new viewthing if the spawn succeeds, 0 if it doesn't.
|
|
//
|
|
// Parameters: const str& -- name of tiki model ("models/eliza.tik")
|
|
// const Vector& -- Position to spawn model at
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::spawnAtPosition( const str& modelName, const Vector& pos )
|
|
{
|
|
// create a new viewthing
|
|
Viewthing *viewthing = new Viewthing;
|
|
current_viewthing = viewthing;
|
|
viewthing->baseorigin = pos ;
|
|
viewthing->setOrigin( viewthing->baseorigin );
|
|
_lastBaseOrigin = viewthing->baseorigin ;
|
|
|
|
if (g_vt_droptoggle->integer)
|
|
{
|
|
viewthing->droptofloor( 10000.0f );
|
|
}
|
|
|
|
viewthing->setAngles( vec_zero );
|
|
|
|
Event* event = new Event( EV_ViewThing_SetModel );
|
|
event->AddString( modelName );
|
|
viewthing->ProcessEvent( event );
|
|
|
|
if ( !gi.IsModel( viewthing->edict->s.modelindex ) )
|
|
{
|
|
delete viewthing;
|
|
current_viewthing = 0 ;
|
|
return;
|
|
}
|
|
_updateViewthingCounts();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: SpawnFromTS
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Called by the ToolServer to viewspawn a model
|
|
// the ToolServer sends over dynamically.
|
|
//
|
|
// Parameters: Event *ev -- Point to event whose first string argument
|
|
// is name of tiki model to reload, the second string
|
|
// is the tiki to respawn. If the second string isn't
|
|
// specified, it respawns the first string
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::SpawnFromTS( Event *ev )
|
|
{
|
|
char *data = (char*)gi.ToolServerGetData();
|
|
|
|
if (!data) // No data? Just abort.
|
|
return;
|
|
|
|
DeleteAll(NULL); // Overkill?
|
|
|
|
char spawnmodel[256], reloadmodel[256];
|
|
|
|
strcpy(reloadmodel, "models/");
|
|
strcat(reloadmodel, ev->GetString(1));
|
|
|
|
if ( ev->NumArgs() > 1 )
|
|
{
|
|
// Already has models/ on it
|
|
strcpy(spawnmodel, ev->GetString(2));
|
|
}
|
|
else
|
|
{
|
|
strcpy(spawnmodel,"models/");
|
|
strcat(spawnmodel, ev->GetString(1));
|
|
}
|
|
|
|
gi.DPrintf("Reloading Model: %s...\n",reloadmodel);
|
|
gi.TikiLoadFromTS(reloadmodel, data);
|
|
// Setting this config string causes the client to reload the surfaces for this tiki
|
|
gi.setConfigstring( CS_DEBUGINFO, va( "reload %s %d", spawnmodel, gi.modelindex(reloadmodel) ) );
|
|
|
|
// Create a new spawn event with item name to send to Spawn function
|
|
Event* spawnEvent = new Event( EV_ViewThing_Spawn);
|
|
spawnEvent->AddString(spawnmodel);
|
|
Spawn(spawnEvent);
|
|
delete spawnEvent;
|
|
spawnEvent = 0 ;
|
|
|
|
gi.setConfigstring( CS_DEBUGINFO, "" );
|
|
}
|
|
|
|
//================================================================
|
|
// Name: Spawn
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Spawns the tiki model specified in the Event's
|
|
// first string argument. The current_viewthing points
|
|
// to the spawned object if the spawn succeeds, 0
|
|
// if it doesn't.
|
|
//
|
|
// The spawned object is dropped straight down if
|
|
// the cvar g_vt_droptoggle is set to true (default).
|
|
// This will cause objects to spawn on the ground.
|
|
//
|
|
// Parameters: Event* -- Point to event whose first string argument
|
|
// is name of tiki model to spawn ("model/eliza.tik")
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::Spawn( Event *ev )
|
|
{
|
|
const char *mdl;
|
|
Viewthing *viewthing;
|
|
Entity *ent;
|
|
Event *event;
|
|
Vector forward;
|
|
Vector up;
|
|
Vector delta;
|
|
|
|
mdl = ev->GetString( 1 );
|
|
if ( !mdl || !mdl[ 0 ] )
|
|
{
|
|
ev->Error( "Must specify a model name" );
|
|
return;
|
|
}
|
|
|
|
// Check if we have a client
|
|
ent = g_entities[ 0 ].entity;
|
|
assert( ent );
|
|
|
|
//-----------------------------------------
|
|
// This if block attempts to keep the current
|
|
// model index of a set up to date when an explicit
|
|
// viewspawn command is issued. If the model that's
|
|
// being spawn is within the set, the index in the
|
|
// set will be updated accordingly.
|
|
//
|
|
// If it isn't found in the set, we simply continue.
|
|
//-----------------------------------------
|
|
if (_numberOfModelsInSet)
|
|
{
|
|
str modelName(mdl);
|
|
int pos = g_vt_modelIndex->integer ;
|
|
if ((pos > 1) && (pos < _modelNamesArray.NumObjects()) && (_modelNamesArray.ObjectAt(pos) != modelName) )
|
|
{
|
|
int pos = _modelNamesArray.IndexOfObject(modelName);
|
|
if (pos)
|
|
{
|
|
gi.cvar_set( "g_vt_modelIndex", va("%d", pos) );
|
|
DeleteCurrentViewthing();
|
|
DisplayCurrentModelInSet();
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// create a new viewthin and set current_viewthing to it.
|
|
viewthing = new Viewthing;
|
|
current_viewthing = viewthing;
|
|
|
|
//FIXME FIXME
|
|
ent->angles.AngleVectors( &forward, NULL, &up );
|
|
|
|
// If _spawnAtLastItemsOrigin is set, we will spawn on
|
|
if (_spawnAtLastItemsOrigin)
|
|
{
|
|
float upOffset = (g_vt_droptoggle->integer) ? 48 : 0 ;
|
|
viewthing->baseorigin = _lastBaseOrigin ;
|
|
viewthing->baseorigin += forward ;
|
|
viewthing->baseorigin += (up * upOffset);
|
|
}
|
|
else {
|
|
viewthing->baseorigin = ent->origin;
|
|
viewthing->baseorigin += ( forward * 48.0f );
|
|
viewthing->baseorigin += ( up * 48.0f );
|
|
}
|
|
|
|
viewthing->setOrigin( viewthing->baseorigin );
|
|
|
|
// Added this so that guns and such can be prevented from falling into the floor.
|
|
// Controlled by viewmodeltoggledrop command. Default is true, so same as old functionality
|
|
if (g_vt_droptoggle->integer)
|
|
{
|
|
viewthing->droptofloor( 10000.0f );
|
|
}
|
|
|
|
viewthing->baseorigin = viewthing->origin;
|
|
_lastBaseOrigin = viewthing->baseorigin ;
|
|
|
|
delta = ent->origin - viewthing->origin;
|
|
viewthing->setAngles( vec_zero );
|
|
|
|
event = new Event( EV_ViewThing_SetModel );
|
|
event->AddString( mdl );
|
|
viewthing->ProcessEvent( event );
|
|
|
|
if ( !gi.IsModel( viewthing->edict->s.modelindex ) )
|
|
{
|
|
ev->Error( "model %s not found, viewmodel not spawned.", mdl );
|
|
delete viewthing;
|
|
current_viewthing = NULL;
|
|
return;
|
|
}
|
|
|
|
_updateViewthingCounts();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: SetModelEvent
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Sets the model for the current viewthing. Passes
|
|
// a SetModelEvent down to the current viewthing. The
|
|
// Event must contain the model name as its first string
|
|
// argument.
|
|
//
|
|
// Parameters: Event* -- First string argument contains model name
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
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" );
|
|
return;
|
|
}
|
|
|
|
if ( !current_viewthing )
|
|
{
|
|
// try to find one on the map
|
|
current_viewthing = G_FindClass( NULL, "viewthing" );
|
|
if ( !current_viewthing )
|
|
{
|
|
ev->Error( "No viewmodel" );
|
|
return;
|
|
}
|
|
}
|
|
|
|
viewthing = ( Viewthing * )( ( Entity * )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 );
|
|
viewthing->UpdateCvars();
|
|
}
|
|
|
|
//================================================================
|
|
// Name: PassEvent
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Passes an event down to the current_viewthing if
|
|
// it is set.
|
|
//
|
|
// Parameters: Event* -- Event to pass
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::PassEvent( Event *ev )
|
|
{
|
|
Viewthing *viewthing;
|
|
Event *event;
|
|
|
|
if ( !current_viewthing )
|
|
{
|
|
ev->Error( "No viewmodel" );
|
|
return;
|
|
}
|
|
|
|
viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
if ( viewthing )
|
|
{
|
|
event = new Event( ev );
|
|
viewthing->ProcessEvent( event );
|
|
}
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// P R O T E C T E D M E T H O D S
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
//================================================================
|
|
// Name: _resetOrigin
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Sets the origin for the current viewthing to be wherever
|
|
// it is at. This also sets the _lastBaseOrigin, which
|
|
// means further relative translations are based from here.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_resetOrigin()
|
|
{
|
|
if (!current_viewthing) return ;
|
|
|
|
Viewthing *viewthing = ( Viewthing*) ( (Entity*) current_viewthing);
|
|
_lastBaseOrigin = viewthing->origin ;
|
|
_setToPosition(_lastBaseOrigin); // just ensure we update cvars
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _setToPosition
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Sets the Position of the current viewthing.
|
|
//
|
|
// Parameters: Vector& pos -- vector of position to set origin to
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_setToPosition( const Vector& pos )
|
|
{
|
|
// Create a new event to pass to viewthing with new origin
|
|
Event* originEvent = new Event(EV_ViewThing_SetOrigin);
|
|
|
|
originEvent->AddFloat(pos.x);
|
|
originEvent->AddFloat(pos.y);
|
|
originEvent->AddFloat(pos.z);
|
|
|
|
// Pass to the viewthing and clean up
|
|
Viewthing *viewthing = (Viewthing*)( (Entity*)current_viewthing );
|
|
viewthing->ChangeOrigin(originEvent);
|
|
delete originEvent ;
|
|
originEvent = 0 ;
|
|
|
|
gi.cvar_set( "g_vt_xtrans", "0" );
|
|
gi.cvar_set( "g_vt_ytrans", "0" );
|
|
gi.cvar_set( "g_vt_ztrans", "0" );
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _selectNext
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Selects the next viewthing in the set of viewthings
|
|
// Selects none if there are no more viewthings.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_selectNext()
|
|
{
|
|
Viewthing *viewthing;
|
|
Entity * ent;
|
|
|
|
ent = G_FindClass( current_viewthing, "viewthing" );
|
|
if ( ent )
|
|
{
|
|
if (current_viewthing)
|
|
{
|
|
viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
viewthing->SetSelected( false );
|
|
}
|
|
|
|
current_viewthing = ent;
|
|
viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
_lastBaseOrigin = viewthing->origin ;
|
|
viewthing->UpdateCvars();
|
|
viewthing->SetSelected( true );
|
|
gi.Printf( "current viewthing model %s.\n", viewthing->model.c_str() );
|
|
_updateViewthingCounts();
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _selectPrev
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Selects the previous viewthing in the set of viewthings.
|
|
// Selects none if there are no previous viewthings.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_selectPrevious()
|
|
{
|
|
Viewthing *viewthing;
|
|
Entity *prev;
|
|
Entity *next;
|
|
|
|
next = NULL;
|
|
do
|
|
{
|
|
prev = next;
|
|
next = G_FindClass( prev, "viewthing" );
|
|
}
|
|
while( next != current_viewthing );
|
|
|
|
if ( prev )
|
|
{
|
|
if (current_viewthing)
|
|
{
|
|
viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
viewthing->SetSelected( false );
|
|
}
|
|
|
|
current_viewthing = prev;
|
|
viewthing = ( Viewthing * )( ( Entity * )current_viewthing );
|
|
_lastBaseOrigin = viewthing->origin ;
|
|
viewthing->UpdateCvars();
|
|
viewthing->SetSelected(true);
|
|
gi.Printf( "current viewthing model %s.\n", viewthing->model.c_str() );
|
|
_updateViewthingCounts();
|
|
}
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _updateViewthingCounts
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Sets the cvars g_vt_viewnumber and g_vt_viewcount
|
|
// appropriately after any change to the number of
|
|
// spawned viewthings in the world. When the loop
|
|
// finishes, g_vt_viewcount is the total number of
|
|
// spawned viewthings and g_vt_viewnumber is position
|
|
// in this list of the current_viewthing.
|
|
//
|
|
// The passed in parameter can be used for manipulating
|
|
// the final count. Because deletion of viewthings is
|
|
// event driven, when we know there is going to be a
|
|
// deletion the deletion hasn't actually occured yet.
|
|
// So it would show up in the count. Hence, we can pass
|
|
// in a -1 to offset the final count appropriately.
|
|
// Hack.
|
|
//
|
|
// Parameters: int countAdjustment -- offset final count (default is 0).
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_updateViewthingCounts(int countAdjustment)
|
|
{
|
|
Entity* next = G_FindClass( NULL, "viewthing");
|
|
int numberOfViewthings = 0 ;
|
|
int currentViewthingIndex = 0 ;
|
|
|
|
while (next)
|
|
{
|
|
numberOfViewthings++ ;
|
|
if (next == current_viewthing)
|
|
{
|
|
currentViewthingIndex = numberOfViewthings ;
|
|
}
|
|
next = G_FindClass( next, "viewthing");
|
|
}
|
|
|
|
gi.cvar_set( "g_vt_viewnumber", va("%d", currentViewthingIndex) );
|
|
gi.cvar_set( "g_vt_viewcount", va("%d", numberOfViewthings + countAdjustment) );
|
|
}
|
|
|
|
//================================================================
|
|
// Name: _randomizeViewthing
|
|
// Class: ViewMaster
|
|
//
|
|
// Description: Randomizes the scaling and rotation of the specified
|
|
// viewthing, based on various cvar settings. These
|
|
// randomizations can be turned on and off individually,
|
|
// but they are only applied if g_vt_viewrandomize is true.
|
|
//
|
|
// The bell curve randomization is done in the scaling section.
|
|
// It works like this:
|
|
// o Add two random values between 0 and 100 and divide total by 100. (Bell curve value--try with two dice)
|
|
// o Get half distance between desired low and high ((high-low) divided by 2)
|
|
// o Scale this half-distance by the bell curve value computed in step 1 (yields # from 0 to 2*half, but tends towards halfway)
|
|
// o Add scaled half to low value, giving bell curve between desired low and high
|
|
//
|
|
// Parameters: Viewthing* -- viewthing to randomize
|
|
//
|
|
// Returns: None
|
|
//
|
|
//================================================================
|
|
void ViewMaster::_randomizeViewthing( Viewthing* viewthingPtr )
|
|
{
|
|
if (!viewthingPtr)
|
|
{
|
|
gi.Printf( "No viewthing to randomize\n");
|
|
return ;
|
|
}
|
|
|
|
if (g_vt_viewsrandomize->integer)
|
|
{
|
|
// Randomly scale
|
|
float die1 = G_Random( 100.0f );
|
|
float die2 = G_Random( 100.0f );
|
|
float scaleValue = (die1 + die2) / 100.0f ;
|
|
|
|
float midpoint = ( (float)g_vt_viewmaxrandomize->integer - (float)g_vt_viewminrandomize->integer) / 2.0f ;
|
|
float adjustment = (float)g_vt_viewminrandomize->integer + (midpoint * scaleValue);
|
|
float scaleFactor = (adjustment / 100.0f);
|
|
|
|
Event* scaleEvent = new Event(EV_ViewThing_SetScale);
|
|
scaleEvent->AddFloat(scaleFactor);
|
|
viewthingPtr->SetScaleEvent(scaleEvent);
|
|
delete scaleEvent ;
|
|
scaleEvent = 0 ;
|
|
}
|
|
|
|
if (g_vt_viewzrandomize->integer)
|
|
{
|
|
// Randomly rotate around z-axis
|
|
Event* rotateEvent = new Event(EV_ViewThing_SetYaw);
|
|
rotateEvent->AddFloat(G_Random(360.0f));
|
|
viewthingPtr->SetYawEvent(rotateEvent);
|
|
delete rotateEvent ;
|
|
rotateEvent = 0 ;
|
|
}
|
|
|
|
if (g_vt_viewyrandomize->integer)
|
|
{
|
|
// Randomly rotate around z-axis
|
|
Event* rotateEvent = new Event(EV_ViewThing_SetPitch);
|
|
rotateEvent->AddFloat(G_Random(360.0f));
|
|
viewthingPtr->SetPitchEvent(rotateEvent);
|
|
delete rotateEvent ;
|
|
rotateEvent = 0 ;
|
|
}
|
|
|
|
if (g_vt_viewxrandomize->integer)
|
|
{
|
|
// Randomly rotate around z-axis
|
|
Event* rotateEvent = new Event(EV_ViewThing_SetRoll);
|
|
rotateEvent->AddFloat(G_Random(360.0f));
|
|
viewthingPtr->SetRollEvent(rotateEvent);
|
|
delete rotateEvent ;
|
|
rotateEvent = 0 ;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
//
|
|
// VIEWTHING
|
|
//
|
|
//------------------------------------------------------------------------
|
|
|
|
CLASS_DECLARATION( Entity, Viewthing, "viewthing" )
|
|
{
|
|
{ &EV_ViewThing_Think, &Viewthing::ThinkEvent },
|
|
{ &EV_ViewThing_LastFrame, &Viewthing::LastFrameEvent },
|
|
{ &EV_ViewThing_ToggleAnimate, &Viewthing::ToggleAnimateEvent },
|
|
{ &EV_ViewThing_SetModel, &Viewthing::SetModelEvent },
|
|
{ &EV_ViewThing_NextFrame, &Viewthing::NextFrameEvent },
|
|
{ &EV_ViewThing_PrevFrame, &Viewthing::PrevFrameEvent },
|
|
{ &EV_ViewThing_NextAnim, &Viewthing::NextAnimEvent },
|
|
{ &EV_ViewThing_PrevAnim, &Viewthing::PrevAnimEvent },
|
|
{ &EV_ViewThing_ScaleUp, &Viewthing::ScaleUpEvent },
|
|
{ &EV_ViewThing_ScaleDown, &Viewthing::ScaleDownEvent },
|
|
{ &EV_ViewThing_SetScale, &Viewthing::SetScaleEvent },
|
|
{ &EV_ViewThing_SetYaw, &Viewthing::SetYawEvent },
|
|
{ &EV_ViewThing_SetPitch, &Viewthing::SetPitchEvent },
|
|
{ &EV_ViewThing_SetRoll, &Viewthing::SetRollEvent },
|
|
{ &EV_ViewThing_SetAngles, &Viewthing::SetAnglesEvent },
|
|
{ &EV_ViewThing_SetStatic, &Viewthing::SetStatic },
|
|
{ &EV_ViewThing_Attach, &Viewthing::AttachModel },
|
|
{ &EV_ViewThing_Detach, &Viewthing::Delete },
|
|
{ &EV_ViewThing_DetachAll, &Viewthing::DetachAll },
|
|
{ &EV_ViewThing_Delete, &Viewthing::Delete },
|
|
{ &EV_ViewThing_SetOrigin, &Viewthing::ChangeOrigin },
|
|
{ &EV_ViewThing_SaveOffSurfaces, &Viewthing::SaveSurfaces },
|
|
{ &EV_ViewThing_PrintTime, &Viewthing::PrintTime },
|
|
{ &EV_ViewThing_SetAnim, &Viewthing::SetAnim },
|
|
{ &EV_ViewThing_NextMorph, &Viewthing::NextMorph },
|
|
{ &EV_ViewThing_PrevMorph, &Viewthing::PrevMorph },
|
|
{ &EV_ViewThing_Morph, &Viewthing::Morph },
|
|
{ &EV_ViewThing_Unmorph, &Viewthing::Unmorph },
|
|
{ &EV_ViewThing_ChangeRoll, &Viewthing::ChangeRollEvent },
|
|
{ &EV_ViewThing_ChangePitch, &Viewthing::ChangePitchEvent },
|
|
{ &EV_ViewThing_ChangeYaw, &Viewthing::ChangeYawEvent },
|
|
{ &EV_ViewThing_Flash, &Viewthing::Flash },
|
|
{ &EV_ViewThing_SetFrame, &Viewthing::SetFrame },
|
|
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
Viewthing::Viewthing( void )
|
|
{
|
|
animate = new Animate( this );
|
|
frame = 0;
|
|
animstate = 0;
|
|
_static = (g_vt_makestatic->integer != 0) ? true : false ;
|
|
_selected = false ;
|
|
_pulseCount = 0 ;
|
|
|
|
setSolidType( SOLID_NOT );
|
|
baseorigin = origin;
|
|
Viewmodel.current_viewthing = this;
|
|
edict->s.eType = ET_MODELANIM;
|
|
edict->s.renderfx |= RF_SHADOW;
|
|
edict->s.renderfx |= RF_SHADOW_PRECISE;
|
|
edict->s.renderfx |= RF_EXTRALIGHT;
|
|
|
|
current_morph = 0;
|
|
|
|
gi.cvar_set( "g_vt_scale", "1.0" );
|
|
gi.cvar_set( "g_vt_roll", "0.0" );
|
|
gi.cvar_set( "g_vt_pitch", "0.0" );
|
|
gi.cvar_set( "g_vt_yaw", "0.0" );
|
|
gi.cvar_set( "g_vt_xtrans", "0.0" );
|
|
gi.cvar_set( "g_vt_ytrans", "0.0" );
|
|
gi.cvar_set( "g_vt_ztrans", "0.0" );
|
|
|
|
|
|
// save off surfaces once the model is spawned
|
|
PostEvent( EV_ViewThing_SaveOffSurfaces, FRAMETIME );
|
|
|
|
PostEvent( EV_ViewThing_Think, FRAMETIME );
|
|
}
|
|
|
|
|
|
void Viewthing::SetSelected( qboolean state )
|
|
{
|
|
_selected = state ;
|
|
_pulseCount = 0 ;
|
|
|
|
if (this->hidden())
|
|
{
|
|
this->showModel();
|
|
}
|
|
}
|
|
|
|
void Viewthing::Flash( Event *ev )
|
|
{
|
|
SetSelected(true);
|
|
}
|
|
|
|
void Viewthing::PrintTime( Event *ev )
|
|
{
|
|
gi.Printf( "ev current frame %d leveltime %.2f\n", ev->GetInteger( 1 ), level.time );
|
|
}
|
|
|
|
void Viewthing::UpdateCvars( qboolean quiet )
|
|
{
|
|
|
|
gi.cvar_set( "viewmodelanim", animate->AnimName() );
|
|
gi.cvar_set( "viewmodeltotaltime", va( "%.3f", animate->AnimTime()) );
|
|
gi.cvar_set( "viewmodelanimframes",va( "%d", animate->NumFrames()) );
|
|
gi.cvar_set( "viewmodelframe", va( "%d", CurrentFrame() ) );
|
|
gi.cvar_set( "viewmodelname", model.c_str() );
|
|
gi.cvar_set( "viewmodelscale", va( "%0.2f", edict->s.scale ) );
|
|
gi.cvar_set( "currentviewthing", model.c_str() );
|
|
gi.cvar_set( "viewthingorigin", va( "%0.2f,%0.2f,%0.2f", edict->s.origin[0],edict->s.origin[1],edict->s.origin[2] ) );
|
|
gi.cvar_set( "viewmodelanimnum", va( "%.3f", ( float )CurrentAnim() / ( float )animate->NumAnims() ) );
|
|
gi.cvar_set( "g_vt_scale", va( "%.2f", edict->s.scale) );
|
|
gi.cvar_set( "g_vt_roll", va( "%.2f", (angles.z <= 180.0f) ? angles.z : (angles.z - 360.0f)) );
|
|
gi.cvar_set( "g_vt_pitch", va( "%.2f", (angles.x <= 180.0f) ? angles.x : (angles.x - 360.0f)) );
|
|
gi.cvar_set( "g_vt_yaw", va( "%.2f", (angles.y <= 180.0f) ? angles.y : (angles.y - 360.0f)) );
|
|
gi.cvar_set( "g_vt_xtrans", va( "%.2f", (Viewmodel._lastBaseOrigin.x - baseorigin.x) ) );
|
|
gi.cvar_set( "g_vt_ytrans", va( "%.2f", (Viewmodel._lastBaseOrigin.y - baseorigin.y) ) );
|
|
gi.cvar_set( "g_vt_ztrans", va( "%.2f", (Viewmodel._lastBaseOrigin.z - baseorigin.z) ) );
|
|
|
|
if ( gi.Morph_NameForNum( edict->s.modelindex, current_morph ) )
|
|
gi.cvar_set( "viewmorphname", gi.Morph_NameForNum( edict->s.modelindex, current_morph ) );
|
|
else
|
|
gi.cvar_set( "viewmorphname", "" );
|
|
|
|
if ( !quiet )
|
|
{
|
|
gi.Printf( "%s, frame %3d, scale %4.2f\n", animate->AnimName(), CurrentFrame(), edict->s.scale );
|
|
}
|
|
}
|
|
|
|
|
|
void Viewthing::ThinkEvent( Event *ev )
|
|
{
|
|
static float startTime = 0 ;
|
|
|
|
if (_selected && (_pulseCount < 20))
|
|
{
|
|
if (startTime == 0.0f)
|
|
{
|
|
startTime = level.time ;
|
|
}
|
|
|
|
if ( (level.time - startTime) > 0.15f)
|
|
{
|
|
if (this->hidden())
|
|
{
|
|
this->showModel();
|
|
}
|
|
else
|
|
{
|
|
this->hideModel();
|
|
}
|
|
startTime = 0.0f ;
|
|
_pulseCount++ ;
|
|
}
|
|
}
|
|
|
|
|
|
int f;
|
|
if (animstate >= 2)
|
|
{
|
|
Vector forward;
|
|
Vector left;
|
|
Vector up;
|
|
Vector realmove;
|
|
|
|
angles.AngleVectors( &forward, &left, &up );
|
|
realmove = ( left * total_delta[1] ) + ( up * total_delta[2] ) + ( forward * total_delta[0] );
|
|
setOrigin( baseorigin + realmove );
|
|
gi.cvar_set( "viewthingorigin", va( "%0.2f,%0.2f,%0.2f", edict->s.origin[0],edict->s.origin[1],edict->s.origin[2] ) );
|
|
}
|
|
PostEvent( EV_ViewThing_Think, FRAMETIME );
|
|
if ( ( animstate > 0 ) && ( Viewmodel.current_viewthing == this ) )
|
|
{
|
|
f = CurrentFrame();
|
|
if ( f != lastframe )
|
|
{
|
|
float time;
|
|
lastframe = f;
|
|
time = f * animate->AnimTime() / (float)animate->NumFrames();
|
|
gi.Printf( "current frame %d time %.2f\n", f, time );
|
|
gi.cvar_set( "viewmodeltime", va( "%.2f", time ) );
|
|
gi.cvar_set( "viewmodelframe", va( "%d", f ) );
|
|
gi.cvar_set( "viewmodelanim", animate->AnimName() );
|
|
}
|
|
}
|
|
}
|
|
|
|
void Viewthing::LastFrameEvent( Event *ev )
|
|
{
|
|
if ( animstate != 3 )
|
|
{
|
|
total_delta = Vector(0, 0, 0);
|
|
}
|
|
}
|
|
|
|
void Viewthing::ToggleAnimateEvent( Event *ev )
|
|
{
|
|
animstate = ( animstate + 1 ) % 4;
|
|
total_delta = Vector(0, 0, 0);
|
|
setOrigin( baseorigin );
|
|
|
|
// reset to a known state
|
|
switch( animstate )
|
|
{
|
|
case 0:
|
|
animate->SetFrame( frame );
|
|
gi.Printf( "Animation stopped.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "Stopped" );
|
|
break;
|
|
case 1:
|
|
animate->NewAnim( CurrentAnim() );
|
|
gi.Printf( "Animation no motion.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "No Motion" );
|
|
break;
|
|
case 2:
|
|
animate->NewAnim( CurrentAnim(), EV_ViewThing_LastFrame );
|
|
gi.Printf( "Animation with motion and looping.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "Motion and Looping" );
|
|
break;
|
|
case 3:
|
|
animate->NewAnim( CurrentAnim(), EV_ViewThing_LastFrame );
|
|
gi.Printf( "Animation with motion no looping.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "Motion and No Looping" );
|
|
break;
|
|
}
|
|
UpdateCvars( true );
|
|
}
|
|
|
|
void Viewthing::SetStatic( Event *ev )
|
|
{
|
|
if (ev->NumArgs() == 1)
|
|
{
|
|
_static = (ev->GetInteger(1)) ? true : false ;
|
|
}
|
|
else
|
|
{
|
|
_static = (g_vt_makestatic->integer != 0) ? true : false ;
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetModelEvent( Event *ev )
|
|
{
|
|
str modelname;
|
|
|
|
modelname = ev->GetString( 1 );
|
|
|
|
setModel( modelname );
|
|
|
|
if ( gi.IsModel( edict->s.modelindex ) )
|
|
{
|
|
// Default the viewthing to an idle animation if the model has one
|
|
|
|
if ( animate->HasAnim( "idle" ) )
|
|
animate->RandomAnimate( "idle" );
|
|
else
|
|
animate->NewAnim( 0 );
|
|
|
|
frame = 0;
|
|
animate->SetFrame( 0 );
|
|
}
|
|
|
|
UpdateCvars();
|
|
}
|
|
|
|
void Viewthing::NextFrameEvent( Event *ev )
|
|
{
|
|
int numframes;
|
|
|
|
numframes = animate->NumFrames();
|
|
if ( numframes )
|
|
{
|
|
frame = (frame+1)%numframes;
|
|
animate->SetFrame( frame );
|
|
animstate = 0;
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::PrevFrameEvent( Event *ev )
|
|
{
|
|
int numframes;
|
|
|
|
numframes = animate->NumFrames();
|
|
if ( numframes )
|
|
{
|
|
frame = (frame-1)%numframes;
|
|
animate->SetFrame( frame );
|
|
animstate = 0;
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetAnim( Event *ev )
|
|
{
|
|
int numanims, anim;
|
|
|
|
numanims = animate->NumAnims();
|
|
if ( numanims )
|
|
{
|
|
// restore original surfaces
|
|
memcpy( edict->s.surfaces, origSurfaces, sizeof( origSurfaces ) );
|
|
|
|
anim = ev->GetFloat( 1 ) * numanims;
|
|
if ( anim >= numanims )
|
|
anim = numanims - 1;
|
|
animate->NewAnim( anim % numanims );
|
|
frame = 0;
|
|
animate->SetFrame( frame );
|
|
animstate = 0;
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetAnim( int num )
|
|
{
|
|
int numanims;
|
|
|
|
numanims = animate->NumAnims();
|
|
if ( numanims )
|
|
{
|
|
// restore original surfaces
|
|
memcpy( edict->s.surfaces, origSurfaces, sizeof( origSurfaces ) );
|
|
|
|
// if ( num >= numanims )
|
|
// num = numanims - 1;
|
|
animate->NewAnim( num );
|
|
animate->SetFrame( frame );
|
|
//animstate = 0;
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::NextAnimEvent( Event *ev )
|
|
{
|
|
int numanims;
|
|
|
|
numanims = animate->NumAnims();
|
|
if ( numanims )
|
|
{
|
|
// restore original surfaces
|
|
memcpy( edict->s.surfaces, origSurfaces, sizeof( origSurfaces ) );
|
|
|
|
animate->NewAnim( ( CurrentAnim() + 1 ) % numanims );
|
|
frame = 0;
|
|
animate->SetFrame( frame );
|
|
animstate = 0;
|
|
gi.Printf( "Animation stopped.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "Stopped" );
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::PrevAnimEvent( Event *ev )
|
|
{
|
|
int anim;
|
|
int numanims;
|
|
|
|
numanims = animate->NumAnims();
|
|
if ( numanims )
|
|
{
|
|
// restore original surfaces
|
|
memcpy( edict->s.surfaces, origSurfaces, sizeof( origSurfaces ) );
|
|
|
|
anim = CurrentAnim() - 1;
|
|
while( anim < 0 )
|
|
{
|
|
anim += numanims;
|
|
}
|
|
animate->NewAnim( anim );
|
|
frame = 0;
|
|
animate->SetFrame( frame );
|
|
animstate = 0;
|
|
gi.Printf( "Animation stopped.\n" );
|
|
gi.cvar_set( "viewmodelanimmode", "Stopped" );
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::ScaleUpEvent( Event *ev )
|
|
{
|
|
edict->s.scale += 0.05f;
|
|
UpdateCvars();
|
|
}
|
|
|
|
void Viewthing::ScaleDownEvent( Event *ev )
|
|
{
|
|
edict->s.scale -= 0.05f;
|
|
UpdateCvars();
|
|
}
|
|
|
|
void Viewthing::SetScaleEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() )
|
|
{
|
|
float s = ev->GetFloat( 1 );
|
|
edict->s.scale = s;
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetYawEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0 )
|
|
{
|
|
angles.setYaw( ev->GetFloat( 1 ) );
|
|
setAngles( angles );
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetPitchEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0 )
|
|
{
|
|
angles.setPitch( ev->GetFloat( 1 ) );
|
|
setAngles( angles );
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetRollEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0 )
|
|
{
|
|
angles.setRoll( ev->GetFloat( 1 ) );
|
|
setAngles( angles );
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::ChangeRollEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0)
|
|
{
|
|
angles.setRoll(angles.roll() + ev->GetFloat( 1 ) );
|
|
setAngles(angles);
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::ChangePitchEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0)
|
|
{
|
|
angles.setPitch(angles.pitch() + ev->GetFloat( 1 ) );
|
|
setAngles(angles);
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
void Viewthing::ChangeYawEvent( Event *ev )
|
|
{
|
|
if ( ev->NumArgs() > 0)
|
|
{
|
|
angles.setYaw(angles.yaw() + ev->GetFloat( 1 ) );
|
|
setAngles(angles);
|
|
UpdateCvars();
|
|
}
|
|
}
|
|
|
|
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.cvar_set( "g_vt_roll", va ("%0.2f", angles.x) );
|
|
gi.cvar_set( "g_vt_pitch", va ("%0.2f", angles.y) );
|
|
gi.cvar_set( "g_vt_yaw", va ("%0.2f", angles.z) );
|
|
gi.Printf( "angles = %0.4f, %0.4f, %0.4f\n", angles.x, angles.y, angles.z );
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
//
|
|
// Name: AttachModel
|
|
// Class: Viewthing
|
|
//
|
|
// Description: Attaches a model to a viewspawned model
|
|
//
|
|
// Parameters: Event *ev
|
|
// string -- model name
|
|
//
|
|
// Returns: None
|
|
//
|
|
//--------------------------------------------------------------
|
|
void Viewthing::AttachModel(Event *ev)
|
|
{
|
|
Event *event = 0;
|
|
Viewthing *child = 0;
|
|
str mdl = ev->GetString(2);
|
|
|
|
child = new Viewthing;
|
|
child->setModel( mdl.c_str() );
|
|
|
|
// Check to make sure it exists.
|
|
if ( !gi.IsModel( child->edict->s.modelindex ) )
|
|
{
|
|
ev->Error( "attachmodel %s not found, attachmodel not spawned.", mdl.c_str() );
|
|
delete child;
|
|
Viewmodel.ProcessEvent(EV_ViewThing_Prev);
|
|
return;
|
|
}
|
|
|
|
// Attach the child
|
|
event = new Event( EV_Attach );
|
|
event->AddEntity( this );
|
|
event->AddString( ev->GetString( 1 ) );
|
|
child->ProcessEvent( event );
|
|
}
|
|
|
|
void Viewthing::Delete( Event *ev )
|
|
{
|
|
Viewmodel.current_viewthing = NULL;
|
|
PostEvent( EV_Remove, 0.0f );
|
|
Viewmodel.PostEvent( EV_ViewThing_Next, 0.0f );
|
|
}
|
|
|
|
void Viewthing::Delete()
|
|
{
|
|
PostEvent( EV_Remove, 0.0f );
|
|
}
|
|
|
|
void Viewthing::DetachAll( Event *ev )
|
|
{
|
|
int i;
|
|
int num;
|
|
Entity * ent;
|
|
|
|
if ( bind_info )
|
|
{
|
|
num = bind_info->numchildren;
|
|
|
|
for (i=0;i<MAX_MODEL_CHILDREN;i++)
|
|
{
|
|
if (!bind_info->children[i])
|
|
continue;
|
|
|
|
ent = ( Entity * )G_GetEntity( bind_info->children[i] );
|
|
ent->PostEvent( EV_Remove, 0.0f );
|
|
num--;
|
|
|
|
if (!num)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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.cvar_set( "g_vt_height", va ("%f", origin.z) );
|
|
UpdateCvars();
|
|
}
|
|
gi.Printf( "vieworigin = x%0.4f y%0.4f z%0.4f\n", origin.x, origin.y, origin.z );
|
|
}
|
|
|
|
void Viewthing::SaveSurfaces( Event *ev )
|
|
{
|
|
memcpy( origSurfaces, edict->s.surfaces, sizeof( origSurfaces ) );
|
|
}
|
|
|
|
|
|
void Viewthing::NextMorph( Event *ev )
|
|
{
|
|
current_morph++;
|
|
|
|
if ( current_morph >= gi.NumMorphs( edict->s.modelindex ) )
|
|
current_morph = 0;
|
|
|
|
if ( gi.Morph_NameForNum( edict->s.modelindex, current_morph ) )
|
|
gi.Printf( "morph %s\n", gi.Morph_NameForNum( edict->s.modelindex, current_morph ) );
|
|
|
|
UpdateCvars( true );
|
|
}
|
|
|
|
void Viewthing::PrevMorph( Event *ev )
|
|
{
|
|
current_morph--;
|
|
|
|
if ( current_morph < 0 )
|
|
current_morph = gi.NumMorphs( edict->s.modelindex ) - 1;
|
|
|
|
if ( gi.Morph_NameForNum( edict->s.modelindex, current_morph ) )
|
|
gi.Printf( "morph %s\n", gi.Morph_NameForNum( edict->s.modelindex, current_morph ) );
|
|
|
|
UpdateCvars( true );
|
|
}
|
|
|
|
void Viewthing::Morph( Event *ev )
|
|
{
|
|
const char *morph_name;
|
|
|
|
morph_name = gi.Morph_NameForNum( edict->s.modelindex, current_morph );
|
|
|
|
if ( morph_name )
|
|
{
|
|
Event *new_event;
|
|
|
|
new_event = new Event ( EV_Morph );
|
|
new_event->AddString( morph_name );
|
|
//new_event->AddFloat( 50 );
|
|
ProcessEvent( new_event );
|
|
}
|
|
}
|
|
|
|
void Viewthing::Unmorph( Event *ev )
|
|
{
|
|
const char *morph_name;
|
|
|
|
morph_name = gi.Morph_NameForNum( edict->s.modelindex, current_morph );
|
|
|
|
if ( morph_name )
|
|
{
|
|
Event *new_event;
|
|
|
|
new_event = new Event ( EV_Unmorph );
|
|
new_event->AddString( morph_name );
|
|
ProcessEvent( new_event );
|
|
}
|
|
}
|
|
|
|
void Viewthing::SetFrame( Event *ev )
|
|
{
|
|
int newframe;
|
|
|
|
newframe = ev->GetInteger(1);
|
|
if ( newframe < animate->NumFrames() )
|
|
{
|
|
animate->SetFrame( newframe );
|
|
animstate = 0;
|
|
UpdateCvars();
|
|
}
|
|
}
|