Git Repos / fte_dogmode / qc / func / rotate.qc
Last update to this file was on 2025-03-30 at 19:29.
Show rotate.qc
//==============================================================================
// func_movewall, func_rotate_door, func_rotate_entity, func_rotate_train
//==============================================================================
//----------------------------------------------------------------------
// Rotate QuickC program
// By Jim Dose' 10/17/96
// Copyright (c)1996 Hipnotic Interactive, Inc.
// All rights reserved.
// Distributed (unsupported) on 3.12.97
//----------------------------------------------------------------------
//======================================================================
// constants
//======================================================================
#ifdef SSQC
//----------------------------------------------------------------------
// func_rotate_entity spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_FUNC_ROTATE_ENTITY_TOGGLE = 1,
SPAWNFLAG_FUNC_ROTATE_ENTITY_START_ON = 2
// 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
} func_rotate_entity_spawnflags;
//----------------------------------------------------------------------
// path_rotate spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_PATH_ROTATE_ROTATION = 1, // spawnflags for path_rotate
SPAWNFLAG_PATH_ROTATE_ANGLES = 2,
SPAWNFLAG_PATH_ROTATE_STOP = 4,
SPAWNFLAG_PATH_ROTATE_NO_ROTATE = 8,
SPAWNFLAG_PATH_ROTATE_DAMAGE = 16,
SPAWNFLAG_PATH_ROTATE_MOVETIME = 32,
SPAWNFLAG_PATH_ROTATE_SET_DAMAGE = 64
// 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 = 1048576, // see base_entities.qc -- CEV
} path_rotate_spawnflags;
//----------------------------------------------------------------------
// func_rotate_door spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_FUNC_ROTATE_DOOR_STAYOPEN = 1
// 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 = 1048576, // see base_entities.qc -- CEV
} func_rotate_door_spawnflags;
//----------------------------------------------------------------------
// func_movewall spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_FUNC_MOVEWALL_VISIBLE = 1,
SPAWNFLAG_FUNC_MOVEWALL_TOUCH = 2,
SPAWNFLAG_FUNC_MOVEWALL_NONBLOCKING = 4
// 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 = 1048576, // see base_entities.qc -- CEV
} func_movewall_spawnflags;
//----------------------------------------------------------------------
// rotate_object_continuously (MG1) spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
SPAWNFLAG_ROTATE_OBJECT_CONTINUOUSLY_START_OFF = 1,
SPAWNFLAG_ROTATE_OBJECT_CONTINUOUSLY_SOLID_BSP = 4
// 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 = 1048576, // see base_entities.qc -- CEV
} rotate_object_continuously_spawnflags;
#endif
#ifdef SSQC
//----------------------------------------------------------------------
// base rotation states -- CEV
//----------------------------------------------------------------------
typedef enum
{
ROTATE_STATE_ACTIVE = 0,
ROTATE_STATE_INACTIVE = 1,
ROTATE_STATE_SPEEDINGUP = 2,
ROTATE_STATE_SLOWINGDOWN = 3,
ROTATE_STATE_CLOSED = 4,
ROTATE_STATE_OPEN = 5,
ROTATE_STATE_OPENING = 6,
ROTATE_STATE_CLOSING = 7
} base_rotate_states;
//----------------------------------------------------------------------
// train rotation states -- CEV
//----------------------------------------------------------------------
typedef enum
{
ROTATE_TRAIN_STATE_WAIT = 0,
ROTATE_TRAIN_STATE_MOVE = 1,
ROTATE_TRAIN_STATE_STOP = 2,
ROTATE_TRAIN_STATE_FIND = 3,
ROTATE_TRAIN_STATE_NEXT = 4
} func_rotate_train_states;
//----------------------------------------------------------------------
// base rotate object states -- CEV
//----------------------------------------------------------------------
typedef enum
{
ROTATE_OBJECT_ROTATE = 0,
ROTATE_OBJECT_MOVEWALL = 1,
ROTATE_OBJECT_SETORIGIN = 2
} base_rotate_object_states;
//----------------------------------------------------------------------
// MG1 continuous rotation states -- CEV
//----------------------------------------------------------------------
typedef enum
{
MG1_ROTATE_STATE_OFF,
MG1_ROTATE_STATE_ACCEL_UP,
MG1_ROTATE_STATE_ON,
MG1_ROTATE_STATE_DECEL_DOWN
} base_rotate_mg1_states;
#endif
//======================================================================
// fields
//======================================================================
#ifdef SSQC
.float duration;
.float endtime;
.float rotate_type;
.vector rotate;
.string event;
.string group;
.string path;
#endif
//======================================================================
// forward declarations
//======================================================================
// base_rotate
#ifdef SSQC
vector(vector ang) base_rotate_normalizeangles;
void() base_rotate_targets;
void() base_rotate_targets_final;
void() base_rotate_set_target_origin;
void() base_rotate_link_targets;
void(float amount) base_rotate_set_damage_on_targets;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) base_rotate_init;
#endif
#ifdef SSQC
strip void() base_rotate;
#endif
// rotate_object_continuously
#ifdef SSQC
// ROTATE_OBJECT_CONTINUOUSLY_MODANGLES(veca)
#endif
#ifdef CSQC
void(float isnew) rotate_object_continuously_netreceive;
#endif
#ifdef SSQC
void() rotate_object_continuously_tick;
void() rotate_object_continuously_tween_tick;
void() rotate_object_continuously_use;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) rotate_object_continuously_init;
#endif
#ifdef SSQC
void() rotate_object_continuously;
#endif
// rotate_object
#ifdef CSQC
void(float isnew) rotate_object_netreceive;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) rotate_object_init;
#endif
#ifdef SSQC
void() rotate_object;
#endif
// func_rotate_entity
#ifdef CSQC
void(float isnew) func_rotate_entity_netreceive;
#endif
#ifdef SSQC
void() func_rotate_entity_firstthink;
void() func_rotate_entity_think;
void() func_rotate_entity_use;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) func_rotate_entity_init;
#endif
#ifdef SSQC
void() func_rotate_entity;
#endif
#ifdef SSQC
// path_rotate
void(entity e) path_rotate_init;
void() path_rotate;
#endif
// func_rotate_train
#ifdef CSQC
void(float isnew) func_rotate_train_netreceive;
#endif
#ifdef SSQC
void() func_rotate_train_think_wait;
void() func_rotate_train_think_stop;
void() func_rotate_train_think_next;
void() func_rotate_train_think_find;
void() func_rotate_train_think;
void() func_rotate_train_use;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) func_rotate_train_init;
#endif
#ifdef SSQC
void() func_rotate_train;
#endif
#ifdef SSQC
// rotate_train
void() rotate_train;
#endif
// func_movewall
#ifdef CSQC
void(float isnew) func_movewall_netreceive;
#endif
#ifdef SSQC
void() func_movewall_touch;
void() func_movewall_blocked;
void() func_movewall_think;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) func_movewall_init;
#endif
#ifdef SSQC
void() func_movewall;
#endif
// func_rotate_door
#ifdef CSQC
void(float isnew) func_rotate_door_netreceive;
#endif
#ifdef SSQC
void() func_rotate_door_reversedirection;
void() func_rotate_door_group_reversedirection;
void() func_rotate_door_think;
void() func_rotate_door_think2;
void() func_rotate_door_use;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) func_rotate_door_init;
#endif
#ifdef SSQC
void() func_rotate_door;
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------
// class base_rotate: base_func
// {
#ifdef SSQC
//--------------------------------------------------------------
// SUB_NormalizeAngles
//--------------------------------------------------------------
vector(vector ang) base_rotate_normalizeangles =
{
while (ang_x > 360)
ang_x = ang_x - 360;
while (ang_x < 0)
ang_x = ang_x + 360;
while (ang_y > 360)
ang_y = ang_y - 360;
while (ang_y < 0)
ang_y = ang_y + 360;
while (ang_z > 360)
ang_z = ang_z - 360;
while (ang_z < 0)
ang_z = ang_z + 360;
return ang;
};
//--------------------------------------------------------------
void() base_rotate_targets =
{
local vector org, vx, vy, vz;
local entity e;
makevectors (self.angles);
e = find (world, targetname, self.target);
while (e)
{
if (!(e.classgroup & CG_FUNC_ROTATE))
{
dprint (sprintf("base_rotate_targets: found "
"unhandled class %s, targetname %s\n",
e.classname, e.targetname));
e = find (e, targetname, self.target);
continue;
}
if (e.rotate_type == ROTATE_OBJECT_SETORIGIN)
{
org = e.oldorigin;
vx = (v_forward * org_x);
vy = (v_right * org_y);
vy = vy * -1;
vz = (v_up * org_z);
e.neworigin = vx + vy + vz;
setorigin (e, e.neworigin + self.origin);
}
else if (e.rotate_type == ROTATE_OBJECT_ROTATE)
{
e.angles = self.angles;
org = e.oldorigin;
vx = (v_forward * org_x);
vy = (v_right * org_y);
vy = vy * -1;
vz = (v_up * org_z);
e.neworigin = vx + vy + vz;
setorigin (e, e.neworigin + self.origin);
}
else
{
org = e.oldorigin;
vx = (v_forward * org_x);
vy = (v_right * org_y);
vy = vy * -1;
vz = (v_up * org_z);
e.neworigin = vx + vy + vz;
e.neworigin = self.origin - self.oldorigin +
(e.neworigin - e.oldorigin);
e.velocity = (e.neworigin - e.origin) * 25;
}
e.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN |
NETFLAG_BASE_ENTITY_ANGLES;
e = find (e, targetname, self.target);
}
};
//--------------------------------------------------------------
void() base_rotate_targets_final =
{
local entity e;
e = find (world, targetname, self.target);
while (e)
{
if (!(e.classgroup & CG_FUNC_ROTATE))
{
dprint (sprintf("base_rotate_targets_final: "
"found unhandled class %s, "
"targetname %s\n",
e.classname, e.targetname));
e = find (e, targetname, self.target);
continue;
}
e.velocity = '0 0 0';
if (e.rotate_type == ROTATE_OBJECT_ROTATE)
e.angles = self.angles;
e.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN |
NETFLAG_BASE_ENTITY_ANGLES;
e = find (e, targetname, self.target);
}
};
//--------------------------------------------------------------
void() base_rotate_set_target_origin =
{
local entity e;
e = find (world, targetname, self.target);
while (e)
{
if (!(e.classgroup & CG_FUNC_ROTATE))
{
dprint (sprintf("base_rotate_set_target_origin"
": found unhandled class %s, "
"targetname %s\n",
e.classname, e.targetname));
e = find (e, targetname, self.target);
continue;
}
if (e.rotate_type == ROTATE_OBJECT_MOVEWALL)
{
setorigin (e, self.origin - self.oldorigin +
(e.neworigin - e.oldorigin));
}
else
{
setorigin (e, e.neworigin + self.origin);
}
e.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN;
e = find (e, targetname, self.target);
}
};
//--------------------------------------------------------------
void() base_rotate_link_targets =
{
local entity e;
local vector tempvec;
self.oldorigin = self.origin;
e = find (world, targetname, self.target);
while (e)
{
if (e.classtype == CT_MISC_ROTATE_OBJECT)
{
e.rotate_type = ROTATE_OBJECT_ROTATE;
e.oldorigin = e.origin - self.oldorigin;
e.neworigin = e.origin - self.oldorigin;
e.owner = self;
}
else if (e.classtype == CT_FUNC_MOVEWALL)
{
e.rotate_type = ROTATE_OBJECT_MOVEWALL;
tempvec = (e.absmin + e.absmax) * 0.5;
e.oldorigin = tempvec - self.oldorigin;
e.neworigin = e.oldorigin;
e.owner = self;
}
else if (e.classgroup & CG_FUNC_ROTATE)
{
e.rotate_type = ROTATE_OBJECT_SETORIGIN;
e.oldorigin = e.origin - self.oldorigin;
e.neworigin = e.origin - self.oldorigin;
}
else
{
dprint (sprintf("base_rotate_link_targets: "
"found an unsupported class %s, "
"targetname %s\n",
e.classname, e.targetname));
}
e = find (e, targetname, self.target);
}
};
//--------------------------------------------------------------
void(float amount) base_rotate_set_damage_on_targets =
{
local entity e;
e = find (world, targetname, self.target);
while (e)
{
if (e.classtype == CT_TRIGGER_HURT)
trigger_hurt_setdamage (e, amount);
else if (e.classtype == CT_FUNC_MOVEWALL)
e.dmg = amount;
e = find (e, targetname, self.target);
}
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) base_rotate_init =
{
e.classgroup |= CG_FUNC_ROTATE;
base_func_init (e);
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
strip void() base_rotate =
{
base_rotate_init (self);
};
#endif
// };
/*QUAKED rotate_object_continuously (0.4 1.0 0.6) (? ? ?) (? ? ?) MG1_ROTATE_START_OFF
Non-solid object that rotates continuously.
Trigger to turn on and off.
*/
//----------------------------------------------------------------------
// class rotate_object_continuously: base_rotate
// {
#ifdef SSQC
//--------------------------------------------------------------
#define ROTATE_OBJECT_CONTINUOUSLY_MODANGLES(veca) \
{ \
while (veca.x > 360) \
veca.x -= 360; \
while (veca.x < 0) \
veca.x += 360; \
while (veca.y > 360) \
veca.y -= 360; \
while (veca.y < 0) \
veca.y += 360; \
while (veca.z > 360) \
veca.z -= 360; \
while (veca.z < 0) \
veca.z += 360; \
}
#endif
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) rotate_object_continuously_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (rotate_object_continuously_init)
if (isnew)
base_entity_que_add (self, QUE_TYPE_ACTOR);
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() rotate_object_continuously_tick =
{
self.angles = self.angles + self.avelocity * server_deltatime;
ROTATE_OBJECT_CONTINUOUSLY_MODANGLES (self.angles)
if (self.angles != self.angles_net)
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
};
//--------------------------------------------------------------
void() rotate_object_continuously_tween_tick =
{
self.speed += self.distance * server_deltatime;
self.speed = bound (0, self.speed, 1);
if (self.speed == 0)
{
self.state = MG1_ROTATE_STATE_OFF;
self.classgroup &= ~CG_FRAMETICK;
return;
}
if (self.speed == 1)
{
self.state = MG1_ROTATE_STATE_ON;
self.tick = rotate_object_continuously_tick;
self.tick ();
return;
}
self.angles = self.angles + self.avelocity *
server_deltatime * self.speed;
ROTATE_OBJECT_CONTINUOUSLY_MODANGLES (self.angles)
if (self.angles != self.angles_net)
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
};
//--------------------------------------------------------------
void() rotate_object_continuously_use =
{
if (self.delay <= 0)
{
// No acceleration, just toggle on or off
if (self.state == MG1_ROTATE_STATE_OFF)
{
self.state = MG1_ROTATE_STATE_ON;
self.classgroup |= CG_FRAMETICK;
}
else
{
self.state = MG1_ROTATE_STATE_OFF;
self.classgroup &= ~CG_FRAMETICK;
}
return;
}
switch (self.state)
{
case MG1_ROTATE_STATE_OFF:
self.state = MG1_ROTATE_STATE_ACCEL_UP;
self.tick =
rotate_object_continuously_tween_tick;
self.distance = fabs (self.distance);
self.classgroup |= CG_FRAMETICK;
return;
case MG1_ROTATE_STATE_ACCEL_UP:
self.state = MG1_ROTATE_STATE_DECEL_DOWN;
self.tick =
rotate_object_continuously_tween_tick;
self.distance = -fabs (self.distance);
return;
case MG1_ROTATE_STATE_ON:
self.state = MG1_ROTATE_STATE_DECEL_DOWN;
self.tick =
rotate_object_continuously_tween_tick;
self.distance = -fabs (self.distance);
return;
case MG1_ROTATE_STATE_DECEL_DOWN:
self.state = MG1_ROTATE_STATE_ACCEL_UP;
self.tick =
rotate_object_continuously_tween_tick;
self.distance = fabs (self.distance);
return;
}
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) rotate_object_continuously_init =
{
e.classname = "rotate_object_continuously";
e.classtype = CT_MISC_ROTATE_OBJECT_CONTINUOUSLY;
base_rotate_init (e);
#ifdef CSQC
setmodelindex (e, e.modelindex);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#endif
#ifdef SSQC
if (!e.avelocity)
e.avelocity = '0 30 0';
if (e.delay > 0)
e.distance = 1 / e.delay;
if (e.spawnflags &
SPAWNFLAG_ROTATE_OBJECT_CONTINUOUSLY_SOLID_BSP)
{
e.movetype = MOVETYPE_PUSH;
e.solid = SOLID_BSP;
}
else
{
e.movetype = MOVETYPE_NONE;
e.solid = SOLID_NOT;
}
e.angles = '0 0 0';
if (e.pos2)
{
e.origin = e.pos2;
setorigin (e, e.origin);
}
setmodel (e, e.model);
e.use = rotate_object_continuously_use;
e.tick = rotate_object_continuously_tick;
if (e.spawnflags &
SPAWNFLAG_ROTATE_OBJECT_CONTINUOUSLY_START_OFF)
{
e.state = MG1_ROTATE_STATE_OFF;
}
else
{
e.state = MG1_ROTATE_STATE_ON;
e.speed = 1;
self.classgroup |= CG_FRAMETICK;
}
e.SendEntity = base_entity_netsend;
e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() rotate_object_continuously =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
rotate_object_continuously_init (self);
};
#endif
// };
/*QUAKED rotate_object (0 .5 .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
This defines an object to be rotated. Used as the target of func_rotate_door.
*/
//----------------------------------------------------------------------
// class rotate_object: base_rotate
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) rotate_object_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (rotate_object_init)
}
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) rotate_object_init =
{
e.classname = "rotate_object";
e.classtype = CT_MISC_ROTATE_OBJECT;
base_rotate_init (e);
#ifdef CSQC
setmodelindex (e, e.modelindex);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#if 0
dprint (sprintf("rotate_object_init: CSQC entnum %g\n",
e.entnum));
#endif
#endif
#ifdef SSQC
e.solid = SOLID_NOT;
e.movetype = MOVETYPE_NONE;
setmodel (e, e.model);
setsize (e, e.mins, e.maxs);
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() rotate_object =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
rotate_object_init (self);
};
#endif
// };
//----------------------------------------------------------------------
// Simple continual rotatation
//----------------------------------------------------------------------
/*QUAKED func_rotate_entity (0 .5 .8) (-8 -8 -8) (8 8 8) TOGGLE START_ON 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
Creates an entity that continually rotates. Can be toggled on and
off if targeted.
TOGGLE = allows the rotation to be toggled on/off
START_ON = wether the entity is spinning when spawned. If TOGGLE is 0, entity can be turned on, but not off.
If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
"rotate" is the rate to rotate.
"target" is the center of rotation.
"speed" is how long the entity takes to go from standing still to full speed and vice-versa.
*/
//----------------------------------------------------------------------
// class func_rotate_entity: base_rotate
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) func_rotate_entity_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (func_rotate_entity_init)
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_entity_firstthink =
{
base_rotate_link_targets ();
if (self.spawnflags & SPAWNFLAG_FUNC_ROTATE_ENTITY_START_ON)
{
self.state = ROTATE_STATE_ACTIVE;
self.think = func_rotate_entity_think;
self.nextthink = time + 0.02;
self.ltime = time;
}
else
{
self.state = ROTATE_STATE_INACTIVE;
self.think = sub_null;
}
self.use = func_rotate_entity_use;
};
//--------------------------------------------------------------
void() func_rotate_entity_think =
{
local float t;
t = time - self.ltime;
self.ltime = time;
if (self.state == ROTATE_STATE_SPEEDINGUP)
{
self.count = self.count + self.cnt * t;
if (self.count > 1)
self.count = 1;
// get rate of rotation
t = t * self.count;
}
else if (self.state == ROTATE_STATE_SLOWINGDOWN)
{
self.count = self.count - self.cnt * t;
if (self.count < 0)
{
base_rotate_targets_final ();
self.state = ROTATE_STATE_INACTIVE;
self.think = sub_null;
return;
}
// get rate of rotation
t = t * self.count;
}
self.angles = self.angles + (self.rotate * t);
self.angles = base_rotate_normalizeangles (self.angles);
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
base_rotate_targets ();
self.nextthink = time + 0.02;
};
//--------------------------------------------------------------
void() func_rotate_entity_use =
{
// change to alternate textures
self.frame = 1 - self.frame;
self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME;
if (self.state == ROTATE_STATE_ACTIVE)
{
if (self.spawnflags &
SPAWNFLAG_FUNC_ROTATE_ENTITY_TOGGLE)
{
if (self.speed)
{
self.count = 1;
self.state = ROTATE_STATE_SLOWINGDOWN;
}
else
{
self.state = ROTATE_STATE_INACTIVE;
self.think = sub_null;
}
}
}
else if (self.state == ROTATE_STATE_INACTIVE)
{
self.think = func_rotate_entity_think;
self.nextthink = time + 0.02;
self.ltime = time;
if (self.speed)
{
self.count = 0;
self.state = ROTATE_STATE_SPEEDINGUP;
}
else
{
self.state = ROTATE_STATE_ACTIVE;
}
}
else if (self.state == ROTATE_STATE_SPEEDINGUP)
{
if (self.spawnflags &
SPAWNFLAG_FUNC_ROTATE_ENTITY_TOGGLE)
{
self.state = ROTATE_STATE_SLOWINGDOWN;
}
}
else
{
self.state = ROTATE_STATE_SPEEDINGUP;
}
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) func_rotate_entity_init =
{
e.classname = "func_rotate_entity";
e.classtype = CT_FUNC_ROTATE_ENTITY;
base_rotate_init (e);
#ifdef CSQC
setmodelindex (e, e.modelindex);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#endif
#ifdef SSQC
e.solid = SOLID_NOT;
e.movetype = MOVETYPE_NONE;
setmodel (e, e.model);
setsize (e, e.mins, e.maxs);
if (e.speed != 0)
e.cnt = 1 / e.speed;
e.tick = base_func_neteval;
e.think = func_rotate_entity_firstthink;
e.nextthink = time + 0.1;
e.ltime = time;
e.SendEntity = base_entity_netsend;
e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_entity =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
func_rotate_entity_init (self);
};
#endif
// };
//----------------------------------------------------------------------
// Train with rotation functionality
//----------------------------------------------------------------------
#ifdef SSQC
/*QUAKED path_rotate (0.5 0.3 0) (-8 -8 -8) (8 8 8) ROTATION ANGLES STOP NO_ROTATE DAMAGE MOVETIME SET_DAMAGE
Path for rotate_train.
ROTATION tells train to rotate at rate specified by "rotate". Use '0 0 0' to stop rotation.
ANGLES tells train to rotate to the angles specified by "angles" while traveling to this path_rotate. Use values < 0 or > 360 to guarantee that it turns in a certain direction. Having this flag set automatically clears any rotation.
STOP tells the train to stop and wait to be retriggered.
NO_ROTATE tells the train to stop rotating when waiting to be triggered.
DAMAGE tells the train to cause damage based on "dmg".
MOVETIME tells the train to interpret "speed" as the length of time to take moving from one corner to another.
SET_DAMAGE tells the train to set all targets damage to "dmg"
"noise" contains the name of the sound to play when train stops.
"noise1" contains the name of the sound to play when train moves.
"event" is a target to trigger when train arrives at path_rotate.
*/
//----------------------------------------------------------------------
// class path_rotate: base_rotate
// {
//--------------------------------------------------------------
void(entity e) path_rotate_init =
{
e.classname = "path_rotate";
e.classtype = CT_PATH_ROTATE;
base_rotate_init (e);
if (e.noise != "")
precache_sound (e.noise);
if (e.noise1 != "")
precache_sound (e.noise1);
};
//--------------------------------------------------------------
void() path_rotate =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
path_rotate_init (self);
};
// };
#endif
/*QUAKED func_rotate_train (0 .5 .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
In path_rotate, set speed to be the new speed of the train after it reaches
the path change. If speed is -1, the train will warp directly to the next
path change after the specified wait time. If MOVETIME is set on the
path_rotate, the train to interprets "speed" as the length of time to
take moving from one corner to another.
"noise" contains the name of the sound to play when train stops.
"noise1" contains the name of the sound to play when train moves.
Both "noise" and "noise1" defaults depend upon "sounds" variable and
can be overridden by the "noise" and "noise1" variable in path_rotate.
Also in path_rotate, if STOP is set, the train will wait until it is
retriggered before moving on to the next goal.
Trains are moving platforms that players can ride.
"path" specifies the first path_rotate and is the starting position.
If the train is the target of a button or trigger, it will not begin moving until activated.
The func_rotate_train entity is the center of rotation of all objects targeted by it.
If "deathtype" is set with a string, this is the message that will appear when a player is killed by the train.
speed default 100
dmg default 0
sounds
1) ratchet metal
*/
//----------------------------------------------------------------------
// class func_rotate_train: base_rotate
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) func_rotate_train_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (func_rotate_train_init)
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_train_think_wait =
{
self.state = ROTATE_TRAIN_STATE_WAIT;
if (self.goalentity.noise != "")
sound (self, CHAN_VOICE, self.goalentity.noise,
VOL_MHI, ATTN_NORM);
else
sound (self, CHAN_VOICE, self.noise,
VOL_MHI, ATTN_NORM);
if (self.goalentity.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.rotate = '0 0 0';
self.angles = self.finalangle;
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
}
if (self.goalentity.spawnflags &
SPAWNFLAG_PATH_ROTATE_NO_ROTATE)
{
self.rotate = '0 0 0';
}
self.endtime = self.ltime + self.goalentity.wait;
self.think1 = func_rotate_train_think_next;
};
//--------------------------------------------------------------
void() func_rotate_train_think_stop =
{
self.state = ROTATE_TRAIN_STATE_STOP;
if (self.goalentity.noise != "")
sound (self, CHAN_VOICE, self.goalentity.noise,
VOL_MHI, ATTN_NORM);
else
sound (self, CHAN_VOICE, self.noise,
VOL_MHI, ATTN_NORM);
if (self.goalentity.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.rotate = '0 0 0';
self.angles = self.finalangle;
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
}
if (self.goalentity.spawnflags &
SPAWNFLAG_PATH_ROTATE_NO_ROTATE)
{
self.rotate = '0 0 0';
}
self.dmg = 0;
self.think1 = func_rotate_train_think_next;
};
//--------------------------------------------------------------
void() func_rotate_train_think_next =
{
local entity current;
local entity targ;
local vector vdestdelta;
local float len, traveltime, div;
local string temp;
self.state = ROTATE_TRAIN_STATE_NEXT;
current = self.goalentity;
targ = find (world, targetname, self.path);
if (targ.classtype != CT_PATH_ROTATE)
objerror ("func_rotate_train_think_next: "
"Next target is not path_rotate!\n");
if (self.goalentity.noise1 != "")
self.noise1 = self.goalentity.noise1;
sound (self, CHAN_VOICE, self.noise1, VOL_MHI, ATTN_NORM);
self.goalentity = targ;
self.path = targ.target;
if (!self.path )
objerror ("func_rotate_train_think_next: "
"no next target!\n");
if (targ.spawnflags & SPAWNFLAG_PATH_ROTATE_STOP)
self.think1 = func_rotate_train_think_stop;
else if (targ.wait)
self.think1 = func_rotate_train_think_wait;
else
self.think1 = func_rotate_train_think_next;
if (current.event != "")
{
// Trigger any events that should happen at the corner.
temp = self.target;
self.target = current.event;
self.message = current.message;
sub_usetargets ();
self.target = temp;
self.message = __NULL__;
}
if (current.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.rotate = '0 0 0';
self.angles = self.finalangle;
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
}
if (current.spawnflags & SPAWNFLAG_PATH_ROTATE_ROTATION)
{
self.rotate = current.rotate;
}
if (current.spawnflags & SPAWNFLAG_PATH_ROTATE_DAMAGE)
{
self.dmg = current.dmg;
}
if (current.spawnflags & SPAWNFLAG_PATH_ROTATE_SET_DAMAGE)
{
base_rotate_set_damage_on_targets (current.dmg);
}
if (current.speed == -1)
{
// Warp to the next path_corner
setorigin (self, targ.origin);
self.endtime = self.ltime + 0.01;
base_rotate_set_target_origin ();
if (targ.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
self.angles = targ.angles;
self.duration = 1; // 1 / duration
self.cnt = time; // start time
self.pos2 = '0 0 0'; // delta
self.pos1 = self.origin; // original position
self.finaldest = self.origin;
self.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN |
NETFLAG_BASE_ENTITY_ANGLES;
}
else
{
self.state = ROTATE_TRAIN_STATE_MOVE;
self.finaldest = targ.origin;
if (self.finaldest == self.origin)
{
self.velocity = '0 0 0';
self.endtime = self.ltime + 0.1;
self.duration = 1; // 1 / duration
self.cnt = time; // start time
self.pos2 = '0 0 0'; // delta
self.pos1 = self.origin;// original position
self.finaldest = self.origin;
return;
}
// set destdelta to the vector needed to move
vdestdelta = self.finaldest - self.origin;
// calculate length of vector
len = vlen (vdestdelta);
if (current.spawnflags & SPAWNFLAG_PATH_ROTATE_MOVETIME)
{
traveltime = current.speed;
}
else
{
// check if there's a speed change
if (current.speed > 0)
self.speed = current.speed;
if (!self.speed)
objerror ("func_rotate_train_think_n"
"ext: No speed is defined!\n");
// divide by speed to get time to reach dest
traveltime = len / self.speed;
}
if (traveltime < 0.1)
{
self.velocity = '0 0 0';
self.endtime = self.ltime + 0.1;
if (targ.spawnflags &
SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.angles = targ.angles;
self.SendFlags |=
NETFLAG_BASE_ENTITY_ANGLES;
}
return;
}
// qcc won't take vec/float
div = 1 / traveltime;
if (targ.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.finalangle = base_rotate_normalizeangles (
targ.angles);
self.rotate = (targ.angles - self.angles) * div;
}
// set endtime to trigger a think when dest is reached
self.endtime = self.ltime + traveltime;
// scale the destdelta vector by the time spent
// traveling to get velocity
self.velocity = vdestdelta * div;
self.duration = div; // 1 / duration
self.cnt = time; // start time
self.pos2 = vdestdelta; // delta
self.pos1 = self.origin; // original position
}
};
//--------------------------------------------------------------
void() func_rotate_train_think_find =
{
local entity targ;
self.state = ROTATE_TRAIN_STATE_FIND;
base_rotate_link_targets ();
// the first target is the point of rotation.
// the second target is the path.
targ = find (world, targetname, self.path);
if (targ.classtype != CT_PATH_ROTATE)
objerror ("func_rotate_train_think_find: "
"Next target is not path_rotate\n");
// Save the current entity
self.goalentity = targ;
if (targ.spawnflags & SPAWNFLAG_PATH_ROTATE_ANGLES)
{
self.angles = targ.angles;
self.finalangle = base_rotate_normalizeangles (
targ.angles);
}
self.path = targ.target;
setorigin (self, targ.origin);
base_rotate_set_target_origin ();
base_rotate_targets_final ();
self.think1 = func_rotate_train_think_next;
if (!self.targetname)
// not triggered, so start immediately
self.endtime = self.ltime + 0.1;
else
self.endtime = 0;
self.duration = 1; // 1 / duration
self.cnt = time; // start time
self.pos2 = '0 0 0'; // delta
self.pos1 = self.origin; // original position
};
//--------------------------------------------------------------
// was rotate_train_think
//--------------------------------------------------------------
void() func_rotate_train_think =
{
local float t, timeelapsed;
t = time - self.ltime;
self.ltime = time;
if ((self.endtime) && (time >= self.endtime))
{
self.endtime = 0;
if (self.state == ROTATE_TRAIN_STATE_MOVE)
{
setorigin (self, self.finaldest);
self.velocity = '0 0 0';
}
if (self.think1)
self.think1 ();
}
else
{
timeelapsed = (time - self.cnt) * self.duration;
if (timeelapsed > 1)
timeelapsed = 1;
setorigin (self, self.pos1 + (self.pos2 * timeelapsed));
}
self.angles = self.angles + (self.rotate * t);
self.angles = base_rotate_normalizeangles (self.angles);
base_rotate_targets ();
self.SendFlags |= NETFLAG_BASE_ENTITY_ORIGIN |
NETFLAG_BASE_ENTITY_ANGLES;
self.nextthink = time + 0.02;
};
//--------------------------------------------------------------
void() func_rotate_train_use =
{
if (self.think1 != func_rotate_train_think_find)
{
if (self.velocity != '0 0 0')
// already activated
return;
if (self.think1)
self.think1 ();
}
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) func_rotate_train_init =
{
e.classname = "func_rotate_train";
e.classtype = CT_FUNC_ROTATE_TRAIN;
base_rotate_init (e);
#ifdef CSQC
setmodelindex (e, e.modelindex);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#endif
#ifdef SSQC
if (!e.speed)
e.speed = 100;
if (!e.target)
objerror ("func_rotate_train: no target!\n");
if (!e.noise)
{
if (e.sounds == 0)
e.noise = "misc/null.wav";
if (e.sounds == 1)
e.noise = "plats/train2.wav";
}
if (!e.noise1)
{
if (e.sounds == 0)
e.noise1 = "misc/null.wav";
if (e.sounds == 1)
e.noise1 = "plats/train1.wav";
}
precache_sound (e.noise);
precache_sound (e.noise1);
e.cnt = 1;
e.solid = SOLID_NOT;
e.movetype = MOVETYPE_STEP;
e.use = func_rotate_train_use;
setmodel (e, e.model);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
// start trains on the second frame, to make sure their
// targets have had a chance to spawn
e.ltime = time;
e.nextthink = e.ltime + 0.1;
e.endtime = e.ltime + 0.1;
e.think = func_rotate_train_think;
e.think1 = func_rotate_train_think_find;
e.state = ROTATE_TRAIN_STATE_FIND;
e.duration = 1; // 1 / duration
e.cnt = 0.1; // start time
e.pos2 = '0 0 0'; // delta
e.pos1 = e.origin; // original position
e.flags |= FL_ONGROUND;
e.tick = base_func_neteval;
e.SendEntity = base_entity_netsend;
e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_train =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
func_rotate_train_init (self);
};
#endif
// };
#ifdef SSQC
//----------------------------------------------------------------------
void() rotate_train =
{
objerror ("rotate_train entities should be changed to "
"rotate_object with\nfunc_rotate_train controllers\n");
};
#endif
//----------------------------------------------------------------------
// Moving clip walls
//----------------------------------------------------------------------
/*QUAKED func_movewall (0 .5 .8) ? VISIBLE TOUCH NONBLOCKING 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
Used to emulate collision on rotating objects.
VISIBLE causes brush to be displayed.
TOUCH specifies whether to cause damage when touched by player.
NONBLOCKING makes the brush non-solid. This is useless if VISIBLE is set.
"dmg" specifies the damage to cause when touched or blocked.
*/
//----------------------------------------------------------------------
// class func_movewall: base_rotate
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) func_movewall_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (func_movewall_init)
if (isnew)
base_entity_que_add (self, QUE_TYPE_ACTOR);
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_movewall_touch =
{
if (time < self.owner.attack_finished)
return;
if (self.dmg)
{
t_damage2 (other, self, self.owner, self.dmg);
self.owner.attack_finished = time + 0.5;
}
else if (self.owner.dmg)
{
t_damage2 (other, self, self.owner, self.owner.dmg);
self.owner.attack_finished = time + 0.5;
}
};
//--------------------------------------------------------------
void() func_movewall_blocked =
{
// handle projectiles -- CEV
if (other.classgroup & CG_PROJECTILE)
{
if (other.mins != '0 0 0' || other.maxs != '0 0 0')
setsize (other, '0 0 0', '0 0 0');
}
if (time < self.owner.attack_finished)
return;
self.owner.attack_finished = time + 0.5;
if (self.owner.classtype == CT_FUNC_ROTATE_DOOR)
sub_runvoidas (self.owner,
func_rotate_door_group_reversedirection);
if (self.dmg)
{
t_damage2 (other, self, self.owner, self.dmg);
self.owner.attack_finished = time + 0.5;
}
else if (self.owner.dmg)
{
t_damage2 (other, self, self.owner, self.owner.dmg);
self.owner.attack_finished = time + 0.5;
}
};
//--------------------------------------------------------------
void() func_movewall_think =
{
self.ltime = time;
self.nextthink = time + 0.02;
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) func_movewall_init =
{
e.classname = "func_movewall";
e.classtype = CT_FUNC_MOVEWALL;
base_rotate_init (e);
#ifdef CSQC
// movewalls seem to always be invisible so don't honor the
// modelindex SSQC sent; set to 0 so it won't be seen -- CEV
setmodelindex (e, 0);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#endif
#ifdef SSQC
e.angles = '0 0 0';
e.movetype = MOVETYPE_PUSH;
if (e.spawnflags & SPAWNFLAG_FUNC_MOVEWALL_TOUCH)
e.touch = func_movewall_touch;
setmodel (e, e.model);
if (!(e.spawnflags & SPAWNFLAG_FUNC_MOVEWALL_VISIBLE))
e.model = __NULL__;
if (e.spawnflags & SPAWNFLAG_FUNC_MOVEWALL_NONBLOCKING)
{
e.solid = SOLID_NOT;
}
else
{
e.solid = SOLID_BSP;
e.blocked = func_movewall_blocked;
}
e.SendEntity = base_entity_netsend;
e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
e.tick = base_func_neteval;
e.think = func_movewall_think;
e.nextthink = time + 0.02;
e.ltime = time;
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_movewall =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
func_movewall_init (self);
};
#endif
// };
//----------------------------------------------------------------------
// Rotating doors
//----------------------------------------------------------------------
/*QUAKED func_rotate_door (0 .5 .8) (-8 -8 -8) (8 8 8) STAYOPEN 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
Creates a door that rotates between two positions around a point of
rotation each time it's triggered.
STAYOPEN tells the door to reopen after closing. This prevents a trigger-
once door from closing again when it's blocked.
"dmg" specifies the damage to cause when blocked. Defaults to 2. Negative numbers indicate no damage.
"speed" specifies how the time it takes to rotate
"sounds"
1) medieval (default)
2) metal
3) base
*/
//----------------------------------------------------------------------
// class func_rotate_door: base_rotate
// {
#ifdef CSQC
//--------------------------------------------------------------
void(float isnew) func_rotate_door_netreceive =
{
// creates the netflag variable -- CEV
BASE_FUNC_NETRECEIVE (func_rotate_door_init)
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_door_reversedirection =
{
local vector start;
// change to alternate textures
self.frame = 1 - self.frame;
self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME;
if (self.state == ROTATE_STATE_CLOSING)
{
start = self.pos1;
self.finaldest = self.pos2;
self.state = ROTATE_STATE_OPENING;
}
else
{
start = self.pos2;
self.finaldest = self.pos1;
self.state = ROTATE_STATE_CLOSING;
}
sound (self, CHAN_VOICE, self.noise2, VOL_MHI, ATTN_NORM);
self.rotate = (self.finaldest - start) * (1 / self.speed);
self.think = func_rotate_door_think;
self.nextthink = time + 0.02;
self.endtime = time + self.speed - (self.endtime - time);
self.ltime = time;
};
//--------------------------------------------------------------
void() func_rotate_door_group_reversedirection =
{
local string name;
local entity e;
// tell all associated rotaters to reverse direction
if (self.group != __NULL__ && self.group != "")
{
name = self.group;
e = find (world, group, name);
while (e)
{
sub_runvoidas (e,
func_rotate_door_reversedirection);
e = find (self, group, name);
}
}
else
{
func_rotate_door_reversedirection ();
}
};
//--------------------------------------------------------------
void() func_rotate_door_think =
{
local float t = time - self.ltime;
self.ltime = time;
if (time < self.endtime)
{
self.angles = self.angles + (self.rotate * t);
base_rotate_targets ();
}
else
{
self.angles = self.finaldest;
base_rotate_targets ();
self.think = func_rotate_door_think2;
}
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES;
self.nextthink = time + 0.01;
};
//--------------------------------------------------------------
void() func_rotate_door_think2 =
{
local float t = time - self.ltime;
self.ltime = time;
// change to alternate textures
self.frame = 1 - self.frame;
self.angles = self.finaldest;
self.SendFlags |= NETFLAG_BASE_ENTITY_ANGLES |
NETFLAG_BASE_ENTITY_FRAME;
if (self.state == ROTATE_STATE_OPENING)
{
self.state = ROTATE_STATE_OPEN;
}
else
{
if (self.spawnflags &
SPAWNFLAG_FUNC_ROTATE_DOOR_STAYOPEN)
{
func_rotate_door_group_reversedirection ();
return;
}
self.state = ROTATE_STATE_CLOSED;
}
sound (self, CHAN_VOICE, self.noise3, VOL_MHI, ATTN_NORM);
self.think = sub_null;
base_rotate_targets_final ();
};
//--------------------------------------------------------------
void() func_rotate_door_use =
{
local vector start;
if ((self.state != ROTATE_STATE_OPEN) &&
(self.state != ROTATE_STATE_CLOSED))
{
return;
}
if (!self.cnt)
{
self.cnt = 1;
base_rotate_link_targets ();
}
// change to alternate textures
self.frame = 1 - self.frame;
if (self.state == ROTATE_STATE_CLOSED)
{
start = self.pos1;
self.finaldest = self.pos2;
self.state = ROTATE_STATE_OPENING;
}
else
{
start = self.pos2;
self.finaldest = self.pos1;
self.state = ROTATE_STATE_CLOSING;
}
sound (self, CHAN_VOICE, self.noise2, VOL_MHI, ATTN_NORM);
self.rotate = (self.finaldest - start) * (1 / self.speed);
self.think = func_rotate_door_think;
self.nextthink = time + 0.01;
self.endtime = time + self.speed;
self.ltime = time;
};
#endif
#if defined(CSQC) || defined(SSQC)
//--------------------------------------------------------------
void(entity e) func_rotate_door_init =
{
e.classname = "func_rotate_door";
e.classtype = CT_FUNC_ROTATE_DOOR;
base_rotate_init (e);
#ifdef CSQC
setmodelindex (e, e.modelindex);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.drawmask = DRAWMASK_NORMAL;
e.predraw = base_func_predraw;
#if 0
dprint (sprintf("func_rotate_door_init: CSQC entnum %g\n",
e.entnum));
#endif
#endif
#ifdef SSQC
if (!e.target)
objerror ("func_rotate_door_init: no target!\n");
e.pos1 = '0 0 0';
e.pos2 = e.angles;
e.angles = e.pos1;
// default to 2 seconds
if (!e.speed)
e.speed = 2;
e.cnt = 0;
if (!e.dmg)
e.dmg = 2;
else if (e.dmg < 0)
e.dmg = 0;
if (e.sounds == 0)
{
// If at least one custom sound is defined, then let's
// ignore the presets and go for the custom sounds,
// otherwise let's use preset #1 by default
if (e.noise1 == "" && e.noise2 == "" && e.noise3 == "")
{
e.sounds = 1;
}
else
{
if (e.noise1 == "")
e.noise1 = "misc/null.wav";
if (e.noise2 == "")
e.noise2 = "misc/null.wav";
if (e.noise3 == "")
e.noise3 = "misc/null.wav";
}
}
if (e.sounds == 1)
{
e.noise1 = "doors/latch2.wav";
e.noise2 = "doors/winch2.wav";
e.noise3 = "doors/drclos4.wav";
}
else if (e.sounds == 2)
{
e.noise2 = "doors/airdoor1.wav";
e.noise1 = "doors/airdoor2.wav";
e.noise3 = e.noise1;
}
else if (e.sounds == 3)
{
e.noise2 = "doors/basesec1.wav";
e.noise1 = "doors/basesec2.wav";
e.noise3 = e.noise1;
}
else if (e.sounds == 4)
{
// added silent option - sounds 4 -- dumptruck_ds
e.noise1 = e.noise2 = "misc/null.wav";
e.noise3 = "misc/null.wav";
}
precache_sound (e.noise1);
precache_sound (e.noise2);
precache_sound (e.noise3);
e.solid = SOLID_NOT;
e.movetype = MOVETYPE_NONE;
setmodel (e, e.model);
setsize (e, e.mins, e.maxs);
setorigin (e, e.origin);
e.state = ROTATE_STATE_CLOSED;
e.use = func_rotate_door_use;
e.think = sub_null;
e.tick = base_func_neteval;
e.SendEntity = base_entity_netsend;
e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
#endif
};
#endif
#ifdef SSQC
//--------------------------------------------------------------
void() func_rotate_door =
{
// new spawnflags for all entities -- iw
if (SUB_Inhibit())
return;
func_rotate_door_init (self);
};
#endif
// };
Return to the top of this page or return to the overview of this repo.
Log rotate.qc
Date | Commit Message | Author | + | - |
---|---|---|---|---|
2025-03-30 | Big commit. Entity networking, etc. | cev | +606 | -142 |
2024-07-17 | pmove changes, smooth crouching | cev | +2 | -2 |
2024-06-26 | pmove fixes, GL now a faux tribolt, wall climbing | cev | +1 | -1 |
2024-06-15 | Major update, committing as-is, will have bugs | cev | +150 | -17 |
2024-03-24 | Fix projectile and func_ blocked interaction | cev | +7 | -1 |
2024-03-24 | 2nd pass refactor, rework QC class structure | cev | +713 | -743 |
2024-02-18 | Client/player, projectiles, entrypoints refactor | cev | +5 | -4 |
2024-01-31 | Class based monster refactor & start projectiles | cev | +19 | -5 |
2024-01-13 | Refactored items into classes, fix teleporttrain | cev | +5 | -5 |
2024-01-09 | Continue OO / Class-based refactor | cev | +1099 | -939 |
2023-12-09 | Start OO / class-based refactor, work on items | cev | +4 | -2 |
2023-12-02 | More refactoring & moving, begin adding mdls & snd | cev | -14 | |
2023-11-27 | Code reorg, minor movement changes, misc | cev | +1250 |
Return to the top of this page or return to the overview of this repo.