Git Repos / fte_dogmode / qc / misc / model.qc
Last update to this file was on 2025-08-13 at 05:20.
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
//==============================================================================
//======================================================================
// 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_SIZE, // model size has changed
NETFLAG_MISC_MODEL_MODEL, // .model has changed
NETFLAG_MISC_MODEL_FRAME, // frame has changed
NETFLAG_MISC_MODEL_STATEFLAGS // active, inactive
} base_misc_model_netflags;
const float NETFLAG_MISC_MODEL_FULLSEND = NETFLAG_MISC_MODEL_ORIGIN |
NETFLAG_MISC_MODEL_SIZE | NETFLAG_MISC_MODEL_MODEL |
NETFLAG_MISC_MODEL_FRAME | NETFLAG_MISC_MODEL_STATEFLAGS;
#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
//======================================================================
// 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
#ifdef SSQC
void(string key, string value) misc_model_init_field;
#endif
#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_SIZE)
{
self.mins_x = ReadCoord ();
self.mins_y = ReadCoord ();
self.mins_z = ReadCoord ();
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_STATEFLAGS)
{
local float s1 = ReadByte ();
if (s1 & STATE_INACTIVE)
self.stateflags |= STATE_INACTIVE;
else
self.stateflags &= ~STATE_INACTIVE;
}
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.stateflags & STATE_INACTIVE))
addentity (self);
return PREDRAW_NEXT;
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
float(entity to, float netflags) base_misc_model_netsend =
{
BASE_ENTITY_WRITECLASSTYPE ()
if (netflags > NETFLAG_MISC_MODEL_FULLSEND)
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_SIZE)
{
WriteCoord (MSG_ENTITY, self.mins_x);
WriteCoord (MSG_ENTITY, self.mins_y);
WriteCoord (MSG_ENTITY, self.mins_z);
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_STATEFLAGS)
{
local float s1 = 0;
if (self.stateflags & STATE_INACTIVE)
s1 |= STATE_INACTIVE;
WriteByte (MSG_ENTITY, s1);
}
return TRUE;
};
//--------------------------------------------------------------
// misc_model_think -- Handles animation for misc_model entity.
//--------------------------------------------------------------
void() base_misc_model_think =
{
self.nextthink = time + fabs (self.speed);
if (self.stateflags & STATE_INACTIVE)
return;
if (self.frame < 0)
self.frame += -1;
else
self.frame += 1;
if (self.spawnflags &
SPAWNFLAG_BASE_MISC_MODEL_BACK_AND_FORTH &&
self.frame < self.first_frame)
{
self.speed *= -1;
self.frame += 2;
}
else if (self.spawnflags &
SPAWNFLAG_BASE_MISC_MODEL_BACK_AND_FORTH &&
self.frame > self.last_frame)
{
self.speed *= -1;
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.stateflags & STATE_INACTIVE)
{
// become active -- CEV
if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID)
self.solid = SOLID_BBOX;
self.model = self.mdl;
setmodel (self, self.model);
setorigin (self, self.origin);
self.stateflags &= ~STATE_INACTIVE;
}
else
{
// become inactive -- CEV
if (self.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID)
self.solid = SOLID_NOT;
self.model = "";
setmodel (self, self.model);
setorigin (self, self.origin);
self.stateflags |= STATE_INACTIVE;
}
// update CSQC
self.SendFlags |= NETFLAG_MISC_MODEL_STATEFLAGS;
};
#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
// {
#ifdef SSQC
//--------------------------------------------------------------
void(string key, string value) misc_model_init_field =
{
switch (key)
{
// rewrite bmFbr's misc_model fields; will be
// consumed in misc_model_init below -- CEV
case "centeroffset":
self.finaldest = stov (value);
break;
case "mdlsz":
self.finalangle = stov (value);
break;
}
};
#endif
#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);
#ifdef CSQC
// only SOLID_BBOX misc_model entities are sent to CSQC -- CEV
e.movetype = MOVETYPE_NONE;
e.solid = SOLID_BBOX;
setmodelindex (e, e.modelindex);
setorigin (e, e.origin);
setsize (e, e.mins, e.maxs);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_misc_model_predraw;
#endif
#ifdef SSQC
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.pos1 && !e.pos2)
{
if (e.finaldest || e.finalangle)
{
// bmFbr's fields (rewritten above) -- CEV
e.pos1.x = e.finaldest.x - (e.finalangle.x / 2);
e.pos1.y = e.finaldest.y - (e.finalangle.y / 2);
e.pos1.z = e.finaldest.z - (e.finalangle.z / 2);
e.pos2.x = e.finaldest.x + (e.finalangle.x / 2);
e.pos2.y = e.finaldest.y + (e.finalangle.y / 2);
e.pos2.z = e.finaldest.z + (e.finalangle.z / 2);
// clear the borrowed fields -- CEV
e.finaldest = '0 0 0';
e.finalangle = '0 0 0';
}
else
{
// set a default size -- CEV
e.pos1 = '-16 -16 -16';
e.pos2 = '16 16 16';
}
}
precache_model (e.mdl);
setmodel (e, e.mdl);
setsize (e, e.pos1, e.pos2);
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.targetname && !e.targetname2 &&
!(e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_GRAVITY) &&
!(e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_SOLID))
{
makestatic (e);
return;
}
// if it has 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;
}
// set state to the reverse of expected 'cause model_use
// is going to toggle it -- CEV
if (e.spawnflags & SPAWNFLAG_BASE_MISC_MODEL_STARTOFF)
e.stateflags &= ~STATE_INACTIVE;
else
e.stateflags |= STATE_INACTIVE;
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;
e.SendFlags = NETFLAG_MISC_MODEL_FULLSEND;
}
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() misc_model =
{
base_mapentity_init_spawndata (misc_model_init_field);
// 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
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2025-08-13 | Another big commit. Item changes, field rework, etc. | cev | +104 | -104 |
2025-03-30 | Big commit. Entity networking, etc. | cev | +132 | -73 |
2024-07-03 | pmove changes and fixes, improved climbing | cev | +1 | -1 |
2024-06-15 | Major update, committing as-is, will have bugs | cev | +182 | -4 |
2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +125 | -111 |
2024-01-31 | Class based monster refactor & start projectiles | cev | +5 | -1 |
2024-01-09 | Continue OO / Class-based refactor | cev | +45 | -31 |
2023-12-09 | Start OO / class-based refactor, work on items | cev | +165 | -154 |
2023-12-02 | More refactoring & moving, begin adding mdls & snd | cev | +194 |
Return to the top of this page or return to the overview of this repo.