// other hud cvars
seta hud_showbinds 1 "what to show in the HUD to indicate certain keys to press: 0 display commands, 1 bound keys, 2 both"
seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited"
+set _hud_showbinds_reload 0 "set it to 1 to reload binds if you changed any. It is reset to 0 automatically"
seta hud_colorflash_alpha 0.5 "starting alpha of the color flash"
--- /dev/null
+// DP console is TURING COMPLETE!
+
+alias _bf_vcall "${$1} ${2- ?}"
+
+// number system
+// Xon RPN: set $_bf_zero 0
+// Xon RPN: alias _bf_inc "rpn /$1 $2 1 add def"
+// Xon RPN: alias _bf_dec "rpn /$1 $2 1 sub def"
+
+// unary
+// decimal | unary
+// 0 | 0
+// 1 | +
+// 2 | ++
+// -1 | -
+// -2 | --
+alias _bf_zero "set $1 0"
+alias _bf_one "set $1 +"
+alias _bf_minus_one "set $1 -"
+alias _bf_return_3 "set $1 $3"
+alias _bf_return_4 "set $1 $4"
+set _bf_zero "0"
+alias _bf_inc_loop1 "set _bf_tmp_$3 _bf_inc_loop2; set _bf_tmp_+$2 _bf_return_3; _bf_vcall _bf_tmp_$3 $*"
+alias _bf_inc_loop2 "set _bf_tmp_$2 _bf_inc_loop3; set _bf_tmp_-$4 _bf_return_4; _bf_vcall _bf_tmp_$2 $*"
+alias _bf_inc_loop3 "_bf_inc_loop1 $1 $2 +$3 -$4"
+alias _bf_inc "set _bf_tmp_$2 _bf_inc_loop1; set _bf_tmp_0 _bf_one; set _bf_tmp_- _bf_zero; _bf_vcall _bf_tmp_$2 $1 $2 + -"
+alias _bf_dec_loop1 "set _bf_tmp_$3 _bf_dec_loop2; set _bf_tmp_-$2 _bf_return_3; _bf_vcall _bf_tmp_$3 $*"
+alias _bf_dec_loop2 "set _bf_tmp_$2 _bf_dec_loop3; set _bf_tmp_+$4 _bf_return_4; _bf_vcall _bf_tmp_$2 $*"
+alias _bf_dec_loop3 "_bf_dec_loop1 $1 $2 -$3 +$4"
+alias _bf_dec "set _bf_tmp_$2 _bf_dec_loop1; set _bf_tmp_0 _bf_minus_one; set _bf_tmp_+ _bf_zero; _bf_vcall _bf_tmp_$2 $1 $2 - +"
+// end of unary
+
+// interpreter state
+set bf_input ""
+alias _bf_clearstate "set _bf_left \"\"; set _bf_right \"\"; set _bf_register $_bf_zero; set _bf_execstack \"\""
+alias _bf_dumpstate "echo rev($_bf_left) < $_bf_register > $_bf_right"
+
+// a STACK!
+alias _bf_pop_get "set $2 \"${3 ?}\"; set $1 \"${4- ?}\""
+alias _bf_pop_dispatch "_bf_pop_get $1 $2 $_bf_popstack_"
+// usage: _bf_pop stackvar outvar defaultvalue
+alias _bf_pop "set _bf_popstack_ \"${$1 ?}\"; set \"_bf_popstack_${$1 ?}\" \"${3 ?}\"; _bf_pop_dispatch $*"
+// usage: _bf_push stackvar value
+alias _bf_push "set $1 \"$2 ${$1 ?}\""
+
+// skip mode: skip until matching ] (1 on _bf_execstack), then continue executing
+alias _bf_skip_ "echo PROGRAMM FELL OFF THE EDGE"
+alias _bf_skip_+ "_bf_skip_${* ?}"
+alias _bf_skip_- "_bf_skip_${* ?}"
+alias _bf_skip_< "_bf_skip_${* ?}"
+alias _bf_skip_> "_bf_skip_${* ?}"
+alias _bf_skip_. "_bf_skip_${* ?}"
+alias _bf_skip_, "_bf_skip_${* ?}"
+alias _bf_skip_endloop_0 "_bf_skip_${* ?}" // continue skipping
+alias _bf_skip_endloop_1 "bf_${* ?}" // back to execution
+alias _bf_skip_endloop_dispatch "_bf_skip_endloop_$_bf_stackval ${* ?}"
+alias _bf_skip_] "_bf_pop _bf_execstack _bf_stackval; _bf_skip_endloop_dispatch ${* ?}"
+alias _bf_skip_[ "_bf_push _bf_execstack 0; _bf_skip_${* ?}"
+// enter
+alias _bf_skiploop "_bf_push _bf_execstack 1; _bf_skip_${* ?}"
+
+// run mode: execute until matching ] (1 on _bf_execstack), then exit
+alias bf_ "echo PROGRAMM FELL OFF THE EDGE"
+alias bf_+ "_bf_inc _bf_register $_bf_register; bf_${* ?}"
+alias bf_- "_bf_dec _bf_register $_bf_register; bf_${* ?}"
+alias bf_< "_bf_push _bf_left $_bf_register; _bf_pop _bf_right _bf_register $_bf_zero; bf_${* ?}"
+alias bf_> "_bf_push _bf_right $_bf_register; _bf_pop _bf_left _bf_register $_bf_zero; bf_${* ?}"
+alias bf_. "echo $_bf_register; bf_${* ?}"
+// note: on EOF, we don't change the register value!
+alias _bf_input_get "set _bf_register $_bf_inputval; bf_${* ?}" // read input
+alias _bf_input_eof "bf_${* ?}" // at EOF, just continue
+alias _bf_input_dispatch "set _bf_inputval_ _bf_input_get; set _bf_inputval_$_bf_inputval _bf_input_eof; _bf_vcall _bf_inputval_ ${* ?}"
+alias bf_, "_bf_pop bf_input _bf_inputval; _bf_input_dispatch ${* ?}"
+alias _bf_endloop_0 "echo IN SKIP MODE, EXCEPT NOT"
+alias _bf_endloop_1 "" // back to caller
+alias _bf_endloop_ "echo PROGRAMM FELL OFF THE EDGE"
+alias _bf_endloop_dispatch "_bf_endloop_$_bf_stackval ${* ?}"
+alias bf_] "_bf_pop _bf_execstack _bf_stackval; _bf_endloop_dispatch ${* ?}"
+// enter
+alias _bf_runloop "_bf_push _bf_execstack 1; bf_$*; bf_[ ${* ?}"
+// loop dispatcher
+alias bf_[ "set _bf_runloop_$_bf_zero _bf_runloop; set _bf_runloop_$_bf_register _bf_skiploop; _bf_vcall _bf_runloop_$_bf_zero ${* ?}"
+
+// start it
+alias bf_exec "_bf_clearstate; _bf_push _bf_execstack 1; bf_$1 ]"
+
+// "cat"
+// Xon RPN: bf_input "1 2 3 4 5"
+bf_input "+ ++ +++ ++++ +++++"
+bf_exec "[ - ] - , + [ - . + [ - ] - , + ]"
+
+// output 42
+// Xon RPN: bf_input "12 6 9"
+bf_input "++++++++++++ ++++++ +++++++++"
+bf_exec ", > , > , < [ > [ - > + > + < < ] > > [ - < < + > > ] < < < - ] < [ - > > > - < < < ] > > > ."
+
+// hello world
+bf_exec "+ + + + + + + + + + [ > + + + + + + + > + + + + + + + + + + > + + + > + < < < < - ] > + + . > + . + + + + + + + . . + + + . > + + . < < + + + + + + + + + + + + + + + . > . + + + . - - - - - - . - - - - - - - - . > + . > ."
set sv_foginterval 1 "force enable fog in regular intervals"
+set g_physical_items 0 "1 uses ODE physics for dropped weapons, 2 for all items, requires physics_ode to be enabled"
+set g_physical_items_damageforcescale 3 "how affected physical weapons are by damage"
+set g_physical_items_reset 1 "return map items to their original lotation after being picked up"
+
// Audio track names (for old-style "cd loop NUMBER" usage)
set _cdtrack_first "1"
alias _cdtrack_0 "g_cdtracks_remaplist \"$g_cdtracks_remaplist $1\""
keys = strcat(keys, ", ", keynumtostring(k));
++l;
- if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit >= l) break;
+ if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit <= l)
+ break;
}
}
hud = getstati(STAT_HUD);
+ if(autocvar__hud_showbinds_reload) // menu can set this one
+ {
+ db_close(binddb);
+ binddb = db_create();
+ cvar_set("_hud_showbinds_reload", "0");
+ }
+
if(checkextension("DP_CSQC_MINFPS_QUALITY"))
view_quality = getproperty(VF_MINFPS_QUALITY);
else
float autocvar_hud_progressbar_alpha;
float autocvar_hud_showbinds;
float autocvar_hud_showbinds_limit;
+float autocvar__hud_showbinds_reload;
float autocvar_hud_shownames;
float autocvar_hud_shownames_enemies;
float autocvar_hud_shownames_crosshairdistance;
me.TD(me, 1, 1, e = makeXonoticButton(_("Clear"), '0 0 0'));
e.onClick = KeyBinder_Bind_Clear;
e.onClickEntity = kb;
+ kb.clearButton = e;
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", _("Pressing \"enter console\" key also closes it")));
ATTRIB(XonoticKeyBinder, inMouseHandler, float, 0)
ATTRIB(XonoticKeyBinder, userbindEditButton, entity, NULL)
ATTRIB(XonoticKeyBinder, keyGrabButton, entity, NULL)
+ ATTRIB(XonoticKeyBinder, clearButton, entity, NULL)
ATTRIB(XonoticKeyBinder, userbindEditDialog, entity, NULL)
METHOD(XonoticKeyBinder, editUserbind, void(entity, string, string, string))
ENDCLASS(XonoticKeyBinder)
if(k != -1)
localcmd("\nbind \"", keynumtostring(k), "\" \"", to, "\"\n");
}
+ if(n)
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_configureXonoticKeyBinder(entity me)
{
return;
me.keyGrabButton.forcePressed = 1;
+ me.clearButton.disabled = 1;
keyGrabber = me;
}
void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
string func;
me.keyGrabButton.forcePressed = 0;
+ me.clearButton.disabled = 0;
+
if(key == K_ESCAPE)
return;
}
localcmd("\nbind \"", keynumtostring(key), "\" \"", func, "\"\n");
localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_editUserbind(entity me, string theName, string theCommandPress, string theCommandRelease)
{
if(!me.userbindEditDialog)
return;
-
+
func = Xonotic_KeyBinds_Functions[me.selectedItem];
if(func == "")
return;
-
+
descr = Xonotic_KeyBinds_Descriptions[me.selectedItem];
if(substring(descr, 0, 1) != "$")
return;
if(!me.userbindEditDialog)
return;
-
+
func = Xonotic_KeyBinds_Functions[me.selectedItem];
if(func == "")
return;
-
+
descr = Xonotic_KeyBinds_Descriptions[me.selectedItem];
if(substring(descr, 0, 1) != "$")
return;
localcmd("\nbind \"", keynumtostring(k), "\" \"", KEY_NOT_BOUND_CMD, "\"\n");
}
localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_clickListBoxItem(entity me, float i, vector where)
{
float autocvar_g_sandbox_object_material_velocity_factor;
float autocvar_g_max_info_autoscreenshot;
float autocvar_physics_ode;
+float autocvar_g_physical_items;
+float autocvar_g_physical_items_damageforcescale;
+float autocvar_g_physical_items_reset;
maxspd_mod = autocvar_sv_spectator_speed_multiplier;
if(!self.spectatorspeed)
self.spectatorspeed = maxspd_mod;
- if(self.impulse && self.impulse <= 19)
+ if(self.impulse && self.impulse <= 19 || self.impulse >= 200 && self.impulse <= 209 || self.impulse >= 220 && self.impulse <= 229)
{
if(self.lastclassname != "player")
{
- if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18)
+ if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || self.impulse >= 200 && self.impulse <= 209)
self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
else if(self.impulse == 11)
self.spectatorspeed = maxspd_mod;
- else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19)
+ else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || self.impulse >= 220 && self.impulse <= 229)
self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
else if(self.impulse >= 1 && self.impulse <= 9)
self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
wep.savenextthink = wep.nextthink;
wep.nextthink = min(wep.nextthink, time + 0.5);
wep.pickup_anyway = TRUE; // these are ALWAYS pickable
+
return s;
}
}
// we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
#ifdef STUFFTO_ENABLED
+ #message "stuffto command enabled"
switch(request)
{
case CMD_REQUEST_COMMAND:
MUTATOR_ADD(mutator_dodging);
if(cvar("g_spawn_near_teammate"))
MUTATOR_ADD(mutator_spawn_near_teammate);
+ if(cvar("g_physical_items"))
+ MUTATOR_ADD(mutator_physical_items);
if(cvar("g_minstagib"))
- MUTATOR_ADD(mutator_minstagib);
-
+ MUTATOR_ADD(mutator_minstagib);
+
if(!g_minstagib)
{
if(cvar("g_invincible_projectiles"))
// good
return 1;
}
- backtrace("WARNING: when adding mutator: adding failed\n");
- Mutator_Remove(func, name);
+
+ backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
+
+ if(func(MUTATOR_ROLLING_BACK) != 0)
+ {
+ // baaaaad
+ error("WARNING: when adding mutator: rolling back failed");
+ }
return 0;
}
void Mutator_Remove(float(float) func, string name)
#define MUTATOR_REMOVING 0
#define MUTATOR_ADDING 1
+#define MUTATOR_ROLLING_BACK 2
typedef float(float) mutatorfunc_t;
float Mutator_Add(mutatorfunc_t func, string name);
void Mutator_Remove(mutatorfunc_t func, string name); // calls error() on fail
#define MUTATOR_DEFINITION(name) float MUTATOR_##name(float mode)
#define MUTATOR_DECLARATION(name) float MUTATOR_##name(float mode)
#define MUTATOR_HOOKFUNCTION(name) float HOOKFUNCTION_##name()
-#define MUTATOR_HOOK(cb,func,order) do { if(mode == MUTATOR_ADDING) { if(!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); if(!CallbackChain_Add(HOOK_##cb,HOOKFUNCTION_##func,order)) { print("HOOK FAILED: ", #func, "\n"); return 1; } } else if(mode == MUTATOR_REMOVING) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
+#define MUTATOR_HOOK(cb,func,order) do { if(mode == MUTATOR_ADDING) { if(!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); if(!CallbackChain_Add(HOOK_##cb,HOOKFUNCTION_##func,order)) { print("HOOK FAILED: ", #func, "\n"); return 1; } } else if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
#define MUTATOR_ONADD if(mode == MUTATOR_ADDING)
#define MUTATOR_ONREMOVE if(mode == MUTATOR_REMOVING)
+#define MUTATOR_ONROLLBACK_OR_REMOVE if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK)
#define MUTATOR_HOOKABLE(cb) entity HOOK_##cb
#define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb)
MUTATOR_HOOKABLE(SetModname);
// OUT
string modname; // name of the mutator/mod if it warrants showing as such in the server browser
+
+MUTATOR_HOOKABLE(Item_Spawn);
+ // called for each item being spawned on a map, including dropped weapons
+ // return 1 to remove an item
+ // INPUT
+ entity self; // the item
MUTATOR_HOOKABLE(SetWeaponreplace);
// IN
ctf_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ctf_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
freezetag_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back freezetag_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
ka_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ka_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
kh_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back kh_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back nb_delayedinit here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
+ }
+
return 0;
}
MUTATOR_ONADD
{
- //InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+ if(time > 1) // game loads at time 1
+ error("This is a game type and it cannot be added at runtime.");
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
// the jump part of the dodge cannot be ramped
.float dodging_single_action;
-void dodging_Initialize() {
- // print("dodging_Initialize\n");
-
- self.last_FORWARD_KEY_time = 0;
- self.last_BACKWARD_KEY_time = 0;
- self.last_RIGHT_KEY_time = 0;
- self.last_LEFT_KEY_time = 0;
- self.last_dodging_time = 0;
- self.dodging_action = 0;
- self.dodging_velocity_gain = 0;
- self.dodging_single_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
-}
-
MUTATOR_HOOKFUNCTION(dodging_GetCvars) {
GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
return 0;
MUTATOR_ONADD
{
g_dodging = 1;
- dodging_Initialize();
}
// this just turns off the cvar.
- MUTATOR_ONREMOVE
- {
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
g_dodging = 0;
}
+ MUTATOR_ONREMOVE
+ {
+ }
+
return 0;
}
if(nt_IsNewToy(i))
get_weaponinfo(i).spawnflags &~= WEP_FLAG_MUTATORBLOCKED;
}
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ float i;
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ if(nt_IsNewToy(i))
+ get_weaponinfo(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ }
+
MUTATOR_ONREMOVE
{
- error("This cannot be removed at runtime\n");
+ print("This cannot be removed at runtime\n");
+ return -1;
}
return 0;
NIX_precache();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
MUTATOR_ONREMOVE
{
// as the PlayerSpawn hook will no longer run, NIX is turned off by this!
--- /dev/null
+.vector spawn_origin, spawn_angles;
+
+void physical_item_think()
+{
+ self.nextthink = time;
+
+ self.alpha = self.owner.alpha; // apply fading and ghosting
+
+ if(!self.cnt) // map item, not dropped
+ {
+ // copy ghost item properties
+ self.colormap = self.owner.colormap;
+ self.colormod = self.owner.colormod;
+ self.glowmod = self.owner.glowmod;
+
+ // if the item is not spawned, make sure the invisible / ghost item returns to its origin and stays there
+ if(autocvar_g_physical_items_reset)
+ {
+ if(self.owner.nextthink > time) // awaiting respawn
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ }
+ else
+ {
+ self.solid = SOLID_CORPSE;
+ self.movetype = MOVETYPE_PHYSICS;
+ }
+ }
+ }
+
+ if(!self.owner.modelindex)
+ remove(self); // the real item is gone, remove this
+}
+
+void physical_item_touch()
+{
+ if(!self.cnt) // not for dropped items
+ if (ITEM_TOUCH_NEEDKILL())
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ }
+}
+
+void physical_item_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if(!self.cnt) // not for dropped items
+ if(ITEM_DAMAGE_NEEDKILL(deathtype))
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ }
+}
+
+MUTATOR_HOOKFUNCTION(item_spawning)
+{
+ if(self.owner == world && autocvar_g_physical_items <= 1)
+ return FALSE;
+ if (self.spawnflags & 1) // floating item
+ return FALSE;
+
+ // The actual item can't be physical and trigger at the same time, so make it invisible and use a second entity for physics.
+ // Ugly hack, but unless SOLID_TRIGGER is gotten to work with MOVETYPE_PHYSICS in the engine it can't be fixed.
+ entity wep;
+ wep = spawn();
+ setmodel(wep, self.model);
+ setsize(wep, self.mins, self.maxs);
+ setorigin(wep, self.origin);
+ wep.angles = self.angles;
+ wep.velocity = self.velocity;
+
+ wep.owner = self;
+ wep.solid = SOLID_CORPSE;
+ wep.movetype = MOVETYPE_PHYSICS;
+ wep.takedamage = DAMAGE_AIM;
+ wep.effects |= EF_NOMODELFLAGS; // disable the spinning
+ wep.colormap = self.owner.colormap;
+ wep.glowmod = self.owner.glowmod;
+ wep.damageforcescale = autocvar_g_physical_items_damageforcescale;
+ wep.dphitcontentsmask = self.dphitcontentsmask;
+ wep.cnt = (self.owner != world);
+
+ wep.think = physical_item_think;
+ wep.nextthink = time;
+ wep.touch = physical_item_touch;
+ wep.event_damage = physical_item_damage;
+
+ wep.spawn_origin = self.origin;
+ wep.spawn_angles = self.angles;
+
+ self.effects |= EF_NODRAW; // hide the original weapon
+ self.movetype = MOVETYPE_FOLLOW;
+ self.aiment = wep; // attach the original weapon
+
+ return FALSE;
+}
+
+MUTATOR_DEFINITION(mutator_physical_items)
+{
+ MUTATOR_HOOK(Item_Spawn, item_spawning, CBC_ORDER_ANY);
+
+ // check if we have a physics engine
+ MUTATOR_ONADD
+ {
+ if not(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE"))
+ {
+ dprint("Warning: Physical items are enabled but no physics engine can be used. Reverting to old items.\n");
+ return -1;
+ }
+ }
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This cannot be removed at runtime\n");
+ return -1;
+ }
+
+ return 0;
+}
//MUTATOR_HOOK(MakePlayerObserver, superspec_MakePlayerObserver, CBC_ORDER_ANY);
MUTATOR_HOOK(ClientDisconnect, superspec_ClientDisconnect, CBC_ORDER_ANY);
- MUTATOR_ONADD
- {
- }
-
- MUTATOR_ONREMOVE
- {
- }
-
return 0;
}
MUTATOR_DECLARATION(mutator_nix);
MUTATOR_DECLARATION(mutator_rocketflying);
MUTATOR_DECLARATION(mutator_spawn_near_teammate);
+MUTATOR_DECLARATION(mutator_physical_items);
MUTATOR_DECLARATION(mutator_vampire);
MUTATOR_DECLARATION(mutator_superspec);
MUTATOR_DECLARATION(mutator_minstagib);
sandbox_Database_Load();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ // nothing to remove
+ }
+
return FALSE;
}
mutators/mutator_rocketflying.qc
mutators/mutator_vampire.qc
mutators/mutator_spawn_near_teammate.qc
+mutators/mutator_physical_items.qc
mutators/sandbox.qc
mutators/mutator_superspec.qc
mutators/mutator_minstagib.qc
Item_Reset();
Net_LinkEntity(self, FALSE, 0, ItemSend);
+
+ // call this hook after everything else has been done
+ if(MUTATOR_CALLHOOK(Item_Spawn))
+ {
+ startitem_failed = TRUE;
+ remove(self);
+ return;
+ }
}
float weaponswapping;