djcev.com

//

Git Repos / fte_dogmode / qc / misc / model.qc

Last update to this file was on 2025-03-30 at 19:29.

Show model.qc

//==============================================================================
// misc_model -- Joshua Skelton -- misc_model.qc requires math.qc
// Author: Joshua Skelton joshua.skelton@gmail.com
// Edited by: Inky 20201219 Minor changes for a better integration with their
// own code
// Edited by: bmFbr for solid and gravity spawnflags and custom bbox sizes
// Edited by: dumptruck_ds to add start and stop animations
//==============================================================================

// TODO CEV the networking could be further optimized

//======================================================================
// constants
//======================================================================

#ifdef SSQC
//----------------------------------------------------------------------
// base_misc_model spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_BASE_MISC_MODEL_GRAVITY = 1,
SPAWNFLAG_BASE_MISC_MODEL_SOLID = 2,
SPAWNFLAG_BASE_MISC_MODEL_BACK_AND_FORTH = 4,
SPAWNFLAG_BASE_MISC_MODEL_ONLY_ONCE = 8,
SPAWNFLAG_BASE_MISC_MODEL_PLAY_COUNT = 16,
SPAWNFLAG_BASE_MISC_MODEL_STARTOFF = 32
// SPAWNFLAG_NOT_ON_EASY = 256, // see base_entities.qc -- CEV
// SPAWNFLAG_NOT_ON_NORMAL = 512,
// SPAWNFLAG_NOT_ON_HARD_OR_NIGHTMARE = 1024,
// SPAWNFLAG_NOT_IN_DEATHMATCH = 2048,
// SPAWNFLAG_NOT_IN_COOP = 4096,
// SPAWNFLAG_NOT_IN_SP = 8192,
// SPAWNFLAG_NOT_ON_SKILL2 = 32768, // see base_entities.qc -- CEV
// SPAWNFLAG_NOT_ON_SKILL3 = 65536, // see base_entities.qc -- CEV
// SPAWNFLAG_CENTERPRINTALL = 131072 // see base_entities.qc -- CEV
} base_misc_model_spawnflags;
#endif

#if defined(CSQC) || defined(SSQC)
//----------------------------------------------------------------------
// generic misc_model networking flags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
NETFLAG_MISC_MODEL_ORIGIN, // origin has changed
NETFLAG_MISC_MODEL_MINS, // model size has changed
NETFLAG_MISC_MODEL_MAXS, // ^^^
NETFLAG_MISC_MODEL_MODEL, // .model has changed
NETFLAG_MISC_MODEL_FRAME, // frame has changed
NETFLAG_MISC_MODEL_FIRSTFRAME, // first frame
NETFLAG_MISC_MODEL_LASTFRAME, // last frame
NETFLAG_MISC_MODEL_STATE // active, inactive
} base_misc_model_netflags;

const float NETFLAG_MISC_MODEL_FULLSEND = NETFLAG_MISC_MODEL_ORIGIN |
NETFLAG_MISC_MODEL_MINS | NETFLAG_MISC_MODEL_MAXS |
NETFLAG_MISC_MODEL_MODEL | NETFLAG_MISC_MODEL_FRAME |
NETFLAG_MISC_MODEL_FIRSTFRAME | NETFLAG_MISC_MODEL_LASTFRAME |
NETFLAG_MISC_MODEL_STATE;
#endif

//======================================================================
// fields
//======================================================================

#if defined(CSQC) || defined(SSQC)
.float first_frame; // The starting frame of the animation
.float last_frame; // The ending frame of the animation
#endif

#ifdef SSQC
.vector mdlsz; // additions by bmFbr for custom bbox
.vector centeroffset;
#endif

//======================================================================
// forward declarations
//======================================================================

// base_misc_model
#ifdef CSQC
void(float isnew) base_misc_model_netreceive;
float() base_misc_model_predraw;
#endif
#ifdef SSQC
float(entity to, float netflags) base_misc_model_netsend;
void() base_misc_model_think;
void() base_misc_model_use;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) base_misc_model_init;
#endif

// misc_model
#if defined(CSQC) || defined(SSQC)
void(entity e) misc_model_init;
#endif
#ifdef SSQC
void() misc_model;
#endif

//------------------------------------------------------------------------------

//----------------------------------------------------------------------
// class base_misc_model: base_mapentity
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) base_misc_model_netreceive =
{
local float newframe = 0;
local float netflags = ReadByte ();

if (netflags & NETFLAG_MISC_MODEL_ORIGIN)
{
self.origin_x = ReadCoord ();
self.origin_y = ReadCoord ();
self.origin_z = ReadCoord ();
}

if (netflags & NETFLAG_MISC_MODEL_MINS)
{
self.mins_x = ReadCoord ();
self.mins_y = ReadCoord ();
self.mins_z = ReadCoord ();
}

if (netflags & NETFLAG_MISC_MODEL_MAXS)
{
self.maxs_x = ReadCoord ();
self.maxs_y = ReadCoord ();
self.maxs_z = ReadCoord ();
}

if (netflags & NETFLAG_MISC_MODEL_MODEL)
self.modelindex = ReadShort ();

if (netflags & NETFLAG_MISC_MODEL_FRAME)
newframe = ReadByte ();

if (netflags & NETFLAG_MISC_MODEL_FIRSTFRAME)
self.first_frame = ReadByte ();

if (netflags & NETFLAG_MISC_MODEL_LASTFRAME)
self.last_frame = ReadByte ();

if (netflags & NETFLAG_MISC_MODEL_STATE)
self.state = ReadByte ();

if (isnew && !(self.predraw))
if (self.classtype == CT_MISC_MODEL)
misc_model_init (self);

if (newframe != self.frame || isnew)
{
self.frame2 = self.frame;
self.lerptime = time;
self.frame = newframe;
}
};

//--------------------------------------------------------------
float() base_misc_model_predraw =
{
// interpolate frame
if (self.lerptime)
self.lerpfrac = 1 - (time - self.lerptime) * 10;

if (self.state == STATE_ACTIVE)
addentity (self);

return PREDRAW_NEXT;
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
float(entity to, float netflags) base_misc_model_netsend =
{
WriteByte (MSG_ENTITY, self.classtype);

if (netflags > 255)
netflags = NETFLAG_MISC_MODEL_FULLSEND;

WriteByte (MSG_ENTITY, netflags);

if (netflags & NETFLAG_MISC_MODEL_ORIGIN)
{
WriteCoord (MSG_ENTITY, self.origin_x);
WriteCoord (MSG_ENTITY, self.origin_y);
WriteCoord (MSG_ENTITY, self.origin_z);
}

if (netflags & NETFLAG_MISC_MODEL_MINS)
{
WriteCoord (MSG_ENTITY, self.mins_x);
WriteCoord (MSG_ENTITY, self.mins_y);
WriteCoord (MSG_ENTITY, self.mins_z);
}

if (netflags & NETFLAG_MISC_MODEL_MAXS)
{
WriteCoord (MSG_ENTITY, self.maxs_x);
WriteCoord (MSG_ENTITY, self.maxs_y);
WriteCoord (MSG_ENTITY, self.maxs_z);
}

if (netflags & NETFLAG_MISC_MODEL_MODEL)
WriteShort (MSG_ENTITY, self.modelindex);

if (netflags & NETFLAG_MISC_MODEL_FRAME)
WriteByte (MSG_ENTITY, self.frame);

if (netflags & NETFLAG_MISC_MODEL_FIRSTFRAME)
WriteByte (MSG_ENTITY, self.first_frame);

if (netflags & NETFLAG_MISC_MODEL_LASTFRAME)
WriteByte (MSG_ENTITY, self.last_frame);

if (netflags & NETFLAG_MISC_MODEL_STATE)
WriteByte (MSG_ENTITY, self.state);

return TRUE;
};

//--------------------------------------------------------------
// misc_model_think -- Handles animation for misc_model entity.
//--------------------------------------------------------------
void() base_misc_model_think =
{
self.nextthink = time + fabs (self.speed);
if (self.estate != STATE_ACTIVE)
return;

self.frame += (self.speed < 0 ? -1 : 1);

if (self.spawnflags &
SPAWNFLAG_BASE_MISC_MODEL_BACK_AND_FORTH &&
self.frame < self.first_frame)
{
self.speed = -1 * self.speed;
self.frame += 2;
}
else if (self.spawnflags &
SPAWNFLAG_BASE_MISC_MODEL_BACK_AND_FORTH &&
self.frame > self.last_frame)
{
self.speed = -1 * self.speed;
self.frame -= 2;
}
else
{
self.frame = wrap (self.frame, self.first_frame,
self.last_frame);
}

// signal CSQC that the frame has changed -- CEV
self.SendFlags |= NETFLAG_MISC_MODEL_FRAME;

if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_ONLY_ONCE &&
self.frame == self.last_frame &&
self.last_frame != self.first_frame)
{
self.nextthink = -1;
}

if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_PLAY_COUNT &&
self.frame == self.last_frame &&
self.last_frame != self.first_frame)
{
if !(self.count)
objerror ("Error: set count to the number of "
" animation cycles!");
self.cnt = self.cnt + 1;
dprint (ftos(self.cnt));
dprint ("\n");
if (self.cnt != self.count)
return FALSE;
else
self.nextthink = -1;
}
};

//--------------------------------------------------------------
void() base_misc_model_use =
{
if (self.state == STATE_ACTIVE)
{
if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID)
self.solid = SOLID_NOT;
self.model = "";

self.state = STATE_INVISIBLE;
setorigin (self, self.origin);
}
else
{
if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID)
self.solid = SOLID_BBOX;
self.model = self.mdl;

self.state = STATE_ACTIVE;
setorigin (self, self.origin);
}

// update CSQC
self.SendFlags |= NETFLAG_MISC_MODEL_STATE;
};
#endif

#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) base_misc_model_init =
{
base_mapentity_init (e);
};
#endif
// };

/*QUAKED misc_model (0 0.5 0.8) (-8 -8 -8) (8 8 8) X X X X X X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
model ({"path" : mdl, "skin" : skin, "frame": frame});
}
An entity for displaying models. A frame range can be given to animate the
model.

mdl: The model to display. Can be of type mdl, bsp, or spr.

frame: The frame to display. Can be used to offset the animation.

first_frame: The starting frame of the animation.

last_frame: The last frame of the animation.
*/
//----------------------------------------------------------------------
// class misc_model: base_misc_model
// {
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) misc_model_init =
{
e.classname = "misc_model";
e.classtype = CT_MISC_MODEL;
base_misc_model_init (e);

local vector vmin, vmax;

#ifdef CSQC
// only SOLID_BBOX misc_model entities are sent to CSQC -- CEV
e.movetype = MOVETYPE_NONE;
e.solid = SOLID_BBOX;
vmin = e.mins;
vmax = e.maxs;
setmodelindex (e, e.modelindex);
setorigin (e, e.origin);
setsize (e, vmin, vmax);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_misc_model_predraw;
#endif

#ifdef SSQC
// TODO CEV
if (known_release == KNOWN_RELEASE_QUAKE3 ||
known_release == KNOWN_RELEASE_CPMA ||
known_release == KNOWN_RELEASE_QUAKELIVE)
{
e.mdl = e.model;
}

if (!e.mdl || e.mdl == "")
objerror ("Model not defined");

if (!e.centeroffset)
e.centeroffset = '0 0 0';

if (!e.mdlsz)
e.mdlsz = '32 32 32';

vmin_x = e.centeroffset_x - (e.mdlsz_x / 2);
vmin_y = e.centeroffset_y - (e.mdlsz_y / 2);
vmin_z = e.centeroffset_z - (e.mdlsz_z / 2);

vmax_x = e.centeroffset_x + (e.mdlsz_x / 2);
vmax_y = e.centeroffset_y + (e.mdlsz_y / 2);
vmax_z = e.centeroffset_z + (e.mdlsz_z / 2);

precache_model (e.mdl);
setmodel (e, e.mdl);
setsize (e, vmin, vmax);

if (e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID)
e.solid = SOLID_BBOX;
else
e.solid = SOLID_NOT;

if (e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_GRAVITY)
e.movetype = MOVETYPE_TOSS;
else
e.movetype = MOVETYPE_NONE;

if (!e.frame)
e.frame = e.first_frame;

// Make static (not animate) if not given a frame range, and
// not affected by gravity; also remains active if it has a
// targetname (so it can be killtargeted/toggled)
if (!e.last_frame &&
!(e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_GRAVITY) &&
!(e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID) &&
!e.targetname &&
!e.targetname2)
// !(e.spawnflags &
// SPAWNFLAG_BASE_MISC_MODEL_DONTMAKESTATIC)
{
makestatic (e);
}

// Make static (not animate) if not given a frame range, and
// not affected by gravity
// changed by bmFbr
// if (!e.last_frame &&
// !(e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_GRAVITY))
// {
// makestatic (e);
// return;
// }

// if it as a custom animation range
if (e.last_frame)
{
// Default animation speed to 10 fps
if (!e.speed)
e.speed = 0.1;
e.think = base_misc_model_think;
e.nextthink = time + e.speed;
}

if (e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_STARTOFF)
e.state = STATE_ACTIVE;
else
e.state = STATE_INVISIBLE;

sub_runvoidas (e, base_misc_model_use);

// network solid misc_model entities to CSQC -- CEV
if (e.solid == SOLID_BBOX)
{
e.SendEntity = base_misc_model_netsend;
// send everything (at first)
e.SendFlags |= NETFLAG_MISC_MODEL_ORIGIN |
NETFLAG_MISC_MODEL_MINS |
NETFLAG_MISC_MODEL_MAXS |
NETFLAG_MISC_MODEL_MODEL |
NETFLAG_MISC_MODEL_FRAME |
NETFLAG_MISC_MODEL_FIRSTFRAME |
NETFLAG_MISC_MODEL_LASTFRAME;
}
#endif
};
#endif

#ifdef SSQC
//--------------------------------------------------------------
void() misc_model =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;

misc_model_init (self);
};
#endif
// };

Return to the top of this page or return to the overview of this repo.

Log model.qc

Return to the top of this page or return to the overview of this repo.