New kill sound.
See merge request xonotic/xonotic-data.pk3dir!431
- wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
- wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
- make
- - EXPECT=fb771b180a47f7acf09eb12dddd391f8
+ - EXPECT=b879b7f0d2da1b120211eabde0caab72
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
-Sat Mar 17 07:23:46 CET 2018
+Fri Apr 20 07:23:54 CEST 2018
QCC=${QCC:-$PWD/../../gmqcc/gmqcc${CMAKE_EXECUTABLE_SUFFIX}}
case $1 in
compile)
- ${CPP} ${@:3} | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' > $2
+ for var in "$@"; do case "$var" in
+ -I*)
+ home=${var:2}
+ break
+ ;;
+ esac; done
+ ${CPP} ${@:3} \
+ | sed -E "s|${home}|~|g" \
+ | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' \
+ > $2
;;
link)
${QCC} \
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
-# Nicky Rowe <nickyrowe@gmail.com>, 2016
+# Nicky Rowe <nickyrowe688@gmail.com>, 2016
+# Nicky Rowe <nickyrowe688@gmail.com>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Xonotic\n"
# Kriss Chr <kriss7475@gmail.com>, 2017
# Piotr Kozica <koza91@gmail.com>, 2016
# Rafał Szymański <okavasly@gmail.com>, 2017
-# Robert Wolniak <robert.wolniak@gmail.com>, 2015
+# Robert Wolniak <robert.wolniak@gmail.com>, 2015,2018
# Sertomas, 2014
msgid ""
msgstr ""
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-09 00:35+0200\n"
-"PO-Revision-Date: 2017-09-20 00:10+0000\n"
-"Last-Translator: Rafał Szymański <okavasly@gmail.com>\n"
+"PO-Revision-Date: 2018-04-19 09:01+0000\n"
+"Last-Translator: Robert Wolniak <robert.wolniak@gmail.com>\n"
"Language-Team: Polish (http://www.transifex.com/team-xonotic/xonotic/"
"language/pl/)\n"
"Language: pl\n"
#: qcsrc/common/gamemodes/gamemode/nexball/weapon.qh:7
msgid "Ball Stealer"
-msgstr ""
+msgstr "ZÅ‚odziej Kuli"
#: qcsrc/common/items/item/armor.qh:111
msgid "Big armor"
"Kill enemies to freeze them, stand next to frozen teammates to revive them; "
"freeze all enemies to win"
msgstr ""
+"Zabijaj przeciwników by ich zamrozić i stój obok członków swojej drużyny by "
+"ich wskrzesić; aby wygrać, zamroź wszystkich wrogów"
#: qcsrc/common/mapinfo.qh:446
msgid "Hold the ball to get points for kills"
"You lost the game!\n"
"Select \"^1Next Match^7\" on the menu for a rematch!"
msgstr ""
+"Przegrana meczu!\n"
+"Wybierz w menu opcję \"^1Następny Mecz^7\" po rewanż!"
#: qcsrc/common/minigames/minigame/pp.qc:444
#: qcsrc/common/minigames/minigame/ttt.qc:325
"You win!\n"
"Select \"^1Next Match^7\" on the menu to start a new match!"
msgstr ""
+"Wygrana!\n"
+"Wybierz w menu opcję \"^1Następny Mecz^7\" by rozpocząć nową grę!"
#: qcsrc/common/minigames/minigame/pp.qc:450
#: qcsrc/common/minigames/minigame/ttt.qc:331
msgid "Select \"^1Next Match^7\" on the menu to start a new match!"
-msgstr ""
+msgstr "Wybierz w menu opcję \"^1Następny Mecz^7\" by rozpocząć nową grę!"
#: qcsrc/common/minigames/minigame/pp.qc:451
#: qcsrc/common/minigames/minigame/ttt.qc:332
msgid "Wait for your opponent to confirm the rematch"
-msgstr ""
+msgstr "Poczekaj aż twój przeciwnik potwierdzi rewanż."
#: qcsrc/common/minigames/minigame/pp.qc:582
#: qcsrc/common/minigames/minigame/ttt.qc:665
#
# Translators:
# Ivan Paulos Tomé <greylica@gmail.com>, 2016
-# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2015-2017
+# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2015-2018
# Mirio <opivy@hotmail.de>, 2017
# NotThatPrivate Yes <henriqueferreira2009@gmail.com>, 2015
# Ricardo Manuel da Cruz Coelho da Silva <ricardo.mccs@gmail.com>, 2015
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-09 00:35+0200\n"
-"PO-Revision-Date: 2017-12-21 15:23+0000\n"
+"PO-Revision-Date: 2018-04-17 20:43+0000\n"
"Last-Translator: Jean Trindade Pereira <jean_trindade2@hotmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.com/team-xonotic/xonotic/"
"language/pt/)\n"
"^3caps^7 How often a flag (CTF) or a key (KeyHunt) was "
"captured\n"
msgstr ""
-"^3capturas^7 Quão frequente uma bandeira (CTF) ou uma chave (KeyHunt) foi "
-"capturada\n"
+"^3capturas^7 Quão frequente uma bandeira (CTF) ou uma chave (Caça a Chaves) "
+"foi capturada\n"
#: qcsrc/client/hud/panel/scoreboard.qc:317
msgid ""
"^3pickups^7 How often a flag (CTF) or a key (KeyHunt) or a "
"ball (Keepaway) was picked up\n"
msgstr ""
-"^3coletas^7. Quão frequente uma bandeira (CTF), uma chave (KeyHunt) ou uma "
-"bola (Keepaway) foi coletada\n"
+"^3coletas^7. Quão frequente uma bandeira (CTF), uma chave (Caça a Chaves) ou "
+"uma bola (Keepaway) foi coletada\n"
#: qcsrc/client/hud/panel/scoreboard.qc:318
msgid "^3captime^7 Time of fastest cap (CTF)\n"
#: qcsrc/common/mapinfo.qh:111
msgid "Last Man Standing"
-msgstr "Last Man Standing"
+msgstr "Último Homem de Pé"
#: qcsrc/common/mapinfo.qh:111
msgid "Survive and kill until the enemies have no lives left"
#: qcsrc/common/mapinfo.qh:249
msgid "Clan Arena"
-msgstr "Clan Arena"
+msgstr "Clã Arena"
#: qcsrc/common/mapinfo.qh:249
msgid "Kill all enemy teammates to win the round"
#: qcsrc/common/mapinfo.qh:287
msgid "Domination"
-msgstr "Domination"
+msgstr "Dominação"
#: qcsrc/common/mapinfo.qh:319
msgid "Gather all the keys to win the round"
#: qcsrc/common/mapinfo.qh:319
msgid "Key Hunt"
-msgstr "Key Hunt"
+msgstr "Caça a Chaves"
#: qcsrc/common/mapinfo.qh:353
msgid "Assault"
-msgstr "Assault"
+msgstr "Assalto"
#: qcsrc/common/mapinfo.qh:353
msgid ""
#: qcsrc/common/mapinfo.qh:371
msgid "Onslaught"
-msgstr "Onslaught"
+msgstr "Massacre"
#: qcsrc/common/mapinfo.qh:387
msgid "Nexball"
-msgstr "Nexball"
+msgstr "Bola Nex"
#: qcsrc/common/mapinfo.qh:387
msgid "Shoot and kick the ball into the enemies goal, keep your goal clean"
#: qcsrc/common/mapinfo.qh:408
msgid "Freeze Tag"
-msgstr "Freeze Tag"
+msgstr "Congela"
#: qcsrc/common/mapinfo.qh:408
msgid ""
#: qcsrc/common/mapinfo.qh:461
msgid "Invasion"
-msgstr "Invasion"
+msgstr "Invasão"
#: qcsrc/common/mapinfo.qh:461
msgid "Survive against waves of monsters"
#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:25
msgid "Flip messages order"
-msgstr "Trocar ordem de notificações"
+msgstr "Trocar ordem de mensagens"
#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:27
#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:15
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:68
msgid "Ammo bar alpha:"
-msgstr "Cor da barra de munições:"
+msgstr "Transparência da barra de munições:"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:74
msgid "Ammo bar color:"
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:204
msgid "Grappling hook"
-msgstr "Gancho (grappling hook)"
+msgstr "Gancho de escalada"
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:205
msgid "Players spawn with the grappling hook"
// Veil (9)
set g_nades_veil_time 8 "Life time of the orb"
-set g_nades_veil_radius 300
+set g_nades_veil_radius 200
// ============
float bgmscriptbufsize;
float bgmscriptbufloaded;
-class(BGMScript) .float bgmscriptline;
-class(BGMScript) .float bgmscriptline0;
-class(BGMScript) .float bgmscriptvolume;
-class(BGMScript) .float bgmscripttime;
-class(BGMScript) .float bgmscriptstate;
-class(BGMScript) .float bgmscriptstatetime;
+classfield(BGMScript) .float bgmscriptline;
+classfield(BGMScript) .float bgmscriptline0;
+classfield(BGMScript) .float bgmscriptvolume;
+classfield(BGMScript) .float bgmscripttime;
+classfield(BGMScript) .float bgmscriptstate;
+classfield(BGMScript) .float bgmscriptstatetime;
float GetAttackDecaySustainAmplitude(float a, float d, float s, float t)
{
if(i >= bgmscriptbufsize)
{
LOG_INFOF("ERROR: bgmscript does not define %s", e.bgmscript);
- strunzone(e.bgmscript);
- e.bgmscript = string_null;
+ strfree(e.bgmscript);
}
}
}
#pragma once
entityclass(BGMScript);
-class(BGMScript) .string bgmscript;
-class(BGMScript) .float bgmscriptattack;
-class(BGMScript) .float bgmscriptdecay;
-class(BGMScript) .float bgmscriptsustain;
-class(BGMScript) .float bgmscriptrelease;
+classfield(BGMScript) .string bgmscript;
+classfield(BGMScript) .float bgmscriptattack;
+classfield(BGMScript) .float bgmscriptdecay;
+classfield(BGMScript) .float bgmscriptsustain;
+classfield(BGMScript) .float bgmscriptrelease;
-class(BGMScript) .float just_toggled;
+classfield(BGMScript) .float just_toggled;
#ifdef CSQC
void BGMScript_InitEntity(entity e);
if (argv(1))
{
// W_FixWeaponOrder will trash argv, so save what we need.
- string thiscvar = strzone(argv(1));
+ string thiscvar = string_null; strcpy(thiscvar, argv(1));
string s = cvar_string(thiscvar);
if (thiscvar == "cl_weaponpriority")
s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
- strunzone(thiscvar);
+ strfree(thiscvar);
return;
}
}
// Drawing stuff
if (hud_skin_prev != autocvar_hud_skin)
{
- if (hud_skin_path)
- strunzone(hud_skin_path);
- hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
- if (hud_skin_prev)
- strunzone(hud_skin_prev);
- hud_skin_prev = strzone(autocvar_hud_skin);
+ strcpy(hud_skin_path, strcat("gfx/hud/", autocvar_hud_skin));
+ strcpy(hud_skin_prev, autocvar_hud_skin);
}
// draw the dock
LOG_TRACE("Automatically fixed wrong/missing panel numbers in _hud_panelorder");
cvar_set("_hud_panelorder", s);
- if(hud_panelorder_prev)
- strunzone(hud_panelorder_prev);
- hud_panelorder_prev = strzone(s);
+ strcpy(hud_panelorder_prev, s);
//now properly set panel_order
tokenize_console(s);
entity panel;
entityclass(HUDPanel);
-class(HUDPanel) .string panel_name;
-class(HUDPanel) .int panel_id;
-class(HUDPanel) .vector current_panel_pos;
-class(HUDPanel) .vector current_panel_size;
-class(HUDPanel) .string current_panel_bg;
-class(HUDPanel) .float current_panel_bg_alpha;
-class(HUDPanel) .float current_panel_bg_border;
-class(HUDPanel) .vector current_panel_bg_color;
-class(HUDPanel) .float current_panel_bg_color_team;
-class(HUDPanel) .float current_panel_bg_padding;
-class(HUDPanel) .float current_panel_fg_alpha;
-class(HUDPanel) .float update_time;
+classfield(HUDPanel) .string panel_name;
+classfield(HUDPanel) .int panel_id;
+classfield(HUDPanel) .vector current_panel_pos;
+classfield(HUDPanel) .vector current_panel_size;
+classfield(HUDPanel) .string current_panel_bg;
+classfield(HUDPanel) .float current_panel_bg_alpha;
+classfield(HUDPanel) .float current_panel_bg_border;
+classfield(HUDPanel) .vector current_panel_bg_color;
+classfield(HUDPanel) .float current_panel_bg_color_team;
+classfield(HUDPanel) .float current_panel_bg_padding;
+classfield(HUDPanel) .float current_panel_fg_alpha;
+classfield(HUDPanel) .float update_time;
float panel_enabled;
vector panel_pos;
vector panel_size;
float panel_bg_padding;
string panel_bg_padding_str;
-class(HUDPanel) .void() panel_draw;
+classfield(HUDPanel) .void() panel_draw;
// chat panel can be reduced / moved while the mapvote is active
// let know the mapvote panel about chat pos and size
} \
} \
} \
- if (panel.current_panel_bg) \
- strunzone(panel.current_panel_bg); \
- panel.current_panel_bg = strzone(panel_bg); \
+ strcpy(panel.current_panel_bg, panel_bg); \
} MACRO_END
// Get value for panel_bg_color: if "" fetch default, else use panel_bg_color. Convert pants, shirt or teamcolor into a vector.
s = strcat(s, ftos(panel_order[i]), " ");
}
cvar_set("_hud_panelorder", s);
- if(hud_panelorder_prev)
- strunzone(hud_panelorder_prev);
- hud_panelorder_prev = strzone(autocvar__hud_panelorder); // prevent HUD_Main from doing useless update, we already updated here
+ strcpy(hud_panelorder_prev, autocvar__hud_panelorder); // prevent HUD_Main from doing useless update, we already updated here
}
void HUD_Panel_Highlight(float allow_move)
cpm_index = CENTERPRINT_MAX_MSGS - 1;
j = cpm_index;
}
- if(centerprint_messages[j])
- strunzone(centerprint_messages[j]);
- centerprint_messages[j] = strzone(strMessage);
+ strcpy(centerprint_messages[j], strMessage);
centerprint_msgID[j] = new_id;
if (duration < 0)
{
centerprint_expire_time[i] = 0;
centerprint_time[i] = 1;
centerprint_msgID[i] = 0;
- if(centerprint_messages[i])
- strunzone(centerprint_messages[i]);
- centerprint_messages[i] = string_null;
+ strfree(centerprint_messages[i]);
}
}
float hud_configure_cp_generation_time;
panel_bg = strcat(hud_skin_path, "/border_default");
if(precache_pic(panel_bg) == "")
panel_bg = "gfx/hud/default/border_default";
- if(panel.current_panel_bg)
- strunzone(panel.current_panel_bg);
- panel.current_panel_bg = strzone(panel_bg);
+ strcpy(panel.current_panel_bg, panel_bg);
chat_panel_modified = true;
}
panel_bg_alpha = max(0.75, panel_bg_alpha);
if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
race_status_time = time + 5;
race_status_prev = race_status;
- if (race_status_name_prev)
- strunzone(race_status_name_prev);
- race_status_name_prev = strzone(race_status_name);
+ strcpy(race_status_name_prev, race_status_name);
}
// race "awards"
if (race_status_time - time <= 0) {
race_status_prev = -1;
race_status = -1;
- if(race_status_name)
- strunzone(race_status_name);
- race_status_name = string_null;
- if(race_status_name_prev)
- strunzone(race_status_name_prev);
- race_status_name_prev = string_null;
+ strfree(race_status_name);
+ strfree(race_status_name_prev);
}
}
{
TC(int, i);
//LOG_INFOF("^xc80 entry %d: %s, %s\n", i, s, s1);
- if (QuickMenu_Page_Description[i])
- strunzone(QuickMenu_Page_Description[i]);
- QuickMenu_Page_Description[i] = strzone(s);
- if (QuickMenu_Page_Command[i])
- strunzone(QuickMenu_Page_Command[i]);
- QuickMenu_Page_Command[i] = strzone(s1);
+ strcpy(QuickMenu_Page_Description[i], s);
+ strcpy(QuickMenu_Page_Command[i], s1);
}
void QuickMenu_Page_ClearEntry(int i)
{
TC(int, i);
- if (QuickMenu_Page_Description[i])
- strunzone(QuickMenu_Page_Description[i]);
- QuickMenu_Page_Description[i] = string_null;
- if (QuickMenu_Page_Command[i])
- strunzone(QuickMenu_Page_Command[i]);
- QuickMenu_Page_Command[i] = string_null;
+ strfree(QuickMenu_Page_Description[i]);
+ strfree(QuickMenu_Page_Command[i]);
QuickMenu_Page_Command_Type[i] = 0;
}
void QuickMenu_Close()
{
- if (QuickMenu_CurrentSubMenu)
- strunzone(QuickMenu_CurrentSubMenu);
- QuickMenu_CurrentSubMenu = string_null;
+ strfree(QuickMenu_CurrentSubMenu);
int i;
for (i = 0; i < QUICKMENU_MAXLINES; ++i)
QuickMenu_Page_ClearEntry(i);
// It assumes submenu open tag is already detected
void QuickMenu_skip_submenu(string submenu)
{
- string s, z_submenu;
- z_submenu = strzone(submenu);
+ string z_submenu = string_null; strcpy(z_submenu, submenu);
for(++QuickMenu_Buffer_Index ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
{
- s = QuickMenu_Buffer_Get();
+ string s = QuickMenu_Buffer_Get();
if(substring(s, 0, 1) != QM_TAG_SUBMENU)
continue;
if(substring(s, 1, -1) == z_submenu) // submenu end
break;
QuickMenu_skip_submenu(substring(s, 1, -1));
}
- strunzone(z_submenu);
+ strfree(z_submenu);
}
bool QuickMenu_IsOpened()
++QuickMenu_Page;
z_submenu = strzone(target_submenu);
- if (QuickMenu_CurrentSubMenu)
- strunzone(QuickMenu_CurrentSubMenu);
- QuickMenu_CurrentSubMenu = strzone(z_submenu);
+ strcpy(QuickMenu_CurrentSubMenu, z_submenu);
QuickMenu_IsLastPage = true;
QuickMenu_Page_Entries = 0;
panel_bg = "gfx/hud/default/border_default"; // fallback
if(!radar_panel_modified && panel_bg != panel.current_panel_bg)
radar_panel_modified = true;
- if(panel.current_panel_bg)
- strunzone(panel.current_panel_bg);
- panel.current_panel_bg = strzone(panel_bg);
+ strcpy(panel.current_panel_bg, panel_bg);
switch(hud_panel_radar_maximized_zoommode)
{
continue;
}
- strunzone(sbt_field_title[sbt_num_fields]);
- sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(str));
+ strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(str));
sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
str = strtolower(str);
}
else if(!have_separator)
{
- strunzone(sbt_field_title[sbt_num_fields]);
- sbt_field_title[sbt_num_fields] = strzone("|");
+ strcpy(sbt_field_title[sbt_num_fields], "|");
sbt_field_size[sbt_num_fields] = stringwidth("|", false, hud_fontsize);
sbt_field[sbt_num_fields] = SP_SEPARATOR;
++sbt_num_fields;
}
if(!have_secondary)
{
- strunzone(sbt_field_title[sbt_num_fields]);
- sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_secondary)));
+ strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(scores_label(ps_secondary)));
sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
sbt_field[sbt_num_fields] = ps_secondary;
++sbt_num_fields;
}
if(!have_primary)
{
- strunzone(sbt_field_title[sbt_num_fields]);
- sbt_field_title[sbt_num_fields] = strzone(TranslateScoresLabel(scores_label(ps_primary)));
+ strcpy(sbt_field_title[sbt_num_fields], TranslateScoresLabel(scores_label(ps_primary)));
sbt_field_size[sbt_num_fields] = stringwidth(sbt_field_title[sbt_num_fields], false, hud_fontsize);
sbt_field[sbt_num_fields] = ps_primary;
++sbt_num_fields;
{
hud_fontsize = HUD_GetFontsize("hud_fontsize");
Scoreboard_initFieldSizes();
- if(hud_fontsize_str)
- strunzone(hud_fontsize_str);
- hud_fontsize_str = strzone(autocvar_hud_fontsize);
+ strcpy(hud_fontsize_str, autocvar_hud_fontsize);
}
}
else {
LOG_INFO(_("^1You must answer before entering hud configure mode"));
cvar_set("_hud_configure", "0");
}
- if(vote_called_vote)
- strunzone(vote_called_vote);
- vote_called_vote = strzone(_("^2Name ^7instead of \"^1Anonymous player^7\" in stats"));
+ strcpy(vote_called_vote, _("^2Name ^7instead of \"^1Anonymous player^7\" in stats"));
uid2name_dialog = 1;
}
if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
{
int weapon_cnt;
- if(weaponorder_bypriority)
- strunzone(weaponorder_bypriority);
- if(weaponorder_byimpulse)
- strunzone(weaponorder_byimpulse);
-
- weaponorder_bypriority = strzone(autocvar_cl_weaponpriority);
- weaponorder_byimpulse = strzone(W_FixWeaponOrder_BuildImpulseList(W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(weaponorder_bypriority))));
+ strcpy(weaponorder_bypriority, autocvar_cl_weaponpriority);
+ strcpy(weaponorder_byimpulse, W_FixWeaponOrder_BuildImpulseList(W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(weaponorder_bypriority))));
weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " ");
weapon_cnt = 0;
if(!(nags & BIT(2)))
{
- if(vote_called_vote)
- strunzone(vote_called_vote);
- vote_called_vote = string_null;
+ strfree(vote_called_vote);
vote_active = 0;
}
else
if(nags & BIT(7))
{
- if(vote_called_vote)
- strunzone(vote_called_vote);
- vote_called_vote = strzone(ReadString());
+ strcpy(vote_called_vote, ReadString());
}
if(nags & 1)
teamplay = _MapInfo_GetTeamPlayBool(gametype);
HUD_ModIcons_SetFunc();
FOREACH(Scores, true, {
- if (scores_label(it)) strunzone(scores_label(it));
- scores_label(it) = strzone(ReadString());
+ strcpy(scores_label(it), ReadString());
scores_flags(it) = ReadByte();
});
for (int i = 0; i < MAX_TEAMSCORE; ++i)
{
- if (teamscores_label(i)) strunzone(teamscores_label(i));
- teamscores_label(i) = strzone(ReadString());
+ strcpy(teamscores_label(i), ReadString());
teamscores_flags(i) = ReadByte();
}
return = true;
arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
- if (forcefog) strunzone(forcefog);
- forcefog = strzone(ReadString());
+ strcpy(forcefog, ReadString());
armorblockpercent = ReadByte() / 255.0;
damagepush_speedfactor = ReadByte() / 255.0;
race_time = ReadInt24_t();
race_previousbesttime = ReadInt24_t();
race_mypreviousbesttime = ReadInt24_t();
- if(race_previousbestname)
- strunzone(race_previousbestname);
string pbestname = ReadString();
if(autocvar_cl_race_cptimes_onlyself)
{
race_previousbesttime = race_mypreviousbesttime;
race_mypreviousbesttime = 0;
- race_previousbestname = strzone("");
+ strcpy(race_previousbestname, "");
}
else
- race_previousbestname = strzone(pbestname);
+ strcpy(race_previousbestname, pbestname);
race_checkpointtime = time;
race_nextbesttime = ReadInt24_t();
if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
race_mybesttime = ReadInt24_t();
- if(race_nextbestname)
- strunzone(race_nextbestname);
string newname = ReadString();
if(autocvar_cl_race_cptimes_onlyself && b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING)
{
race_nextbesttime = race_mybesttime;
race_mybesttime = 0;
- race_nextbestname = strzone("");
+ strcpy(race_nextbestname, "");
}
else
- race_nextbestname = strzone(newname);
+ strcpy(race_nextbestname, newname);
break;
case RACE_NET_CHECKPOINT_HIT_RACE:
race_mycheckpointlapsdelta = ReadByte();
if(race_mycheckpointlapsdelta >= 128)
race_mycheckpointlapsdelta -= 256;
- if(race_mycheckpointenemy)
- strunzone(race_mycheckpointenemy);
int who = ReadByte();
if(who)
- race_mycheckpointenemy = strzone(entcs_GetName(who - 1));
+ strcpy(race_mycheckpointenemy, entcs_GetName(who - 1));
else
- race_mycheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
+ strcpy(race_mycheckpointenemy, ""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT:
race_othercheckpointlapsdelta = ReadByte();
if(race_othercheckpointlapsdelta >= 128)
race_othercheckpointlapsdelta -= 256;
- if(race_othercheckpointenemy)
- strunzone(race_othercheckpointenemy);
int what = ReadByte();
if(what)
- race_othercheckpointenemy = strzone(entcs_GetName(what - 1));
+ strcpy(race_othercheckpointenemy, entcs_GetName(what - 1));
else
- race_othercheckpointenemy = strzone(""); // TODO: maybe string_null works fine here?
+ strcpy(race_othercheckpointenemy, ""); // TODO: maybe string_null works fine here?
break;
case RACE_NET_PENALTY_RACE:
race_penaltyeventtime = time;
race_penaltytime = ReadShort();
//race_penaltyaccumulator += race_penaltytime;
- if(race_penaltyreason)
- strunzone(race_penaltyreason);
- race_penaltyreason = strzone(ReadString());
+ strcpy(race_penaltyreason, ReadString());
break;
case RACE_NET_PENALTY_QUALIFYING:
race_penaltyeventtime = time;
race_penaltytime = ReadShort();
race_penaltyaccumulator += race_penaltytime;
- if(race_penaltyreason)
- strunzone(race_penaltyreason);
- race_penaltyreason = strzone(ReadString());
+ strcpy(race_penaltyreason, ReadString());
break;
case RACE_NET_SERVER_RECORD:
break;
case RACE_NET_SPEED_AWARD:
race_speedaward = ReadInt24_t() * GetSpeedUnitFactor(autocvar_hud_panel_physics_speed_unit);
- if(race_speedaward_holder)
- strunzone(race_speedaward_holder);
- race_speedaward_holder = strzone(ReadString());
- if(race_speedaward_unit)
- strunzone(race_speedaward_unit);
- race_speedaward_unit = strzone(GetSpeedUnit(autocvar_hud_panel_physics_speed_unit));
+ strcpy(race_speedaward_holder, ReadString());
+ strcpy(race_speedaward_unit, GetSpeedUnit(autocvar_hud_panel_physics_speed_unit));
break;
case RACE_NET_SPEED_AWARD_BEST:
race_speedaward_alltimebest = ReadInt24_t() * GetSpeedUnitFactor(autocvar_hud_panel_physics_speed_unit);
- if(race_speedaward_alltimebest_holder)
- strunzone(race_speedaward_alltimebest_holder);
- race_speedaward_alltimebest_holder = strzone(ReadString());
- if(race_speedaward_alltimebest_unit)
- strunzone(race_speedaward_alltimebest_unit);
- race_speedaward_alltimebest_unit = strzone(GetSpeedUnit(autocvar_hud_panel_physics_speed_unit));
+ strcpy(race_speedaward_alltimebest_holder, ReadString());
+ strcpy(race_speedaward_alltimebest_unit, GetSpeedUnit(autocvar_hud_panel_physics_speed_unit));
break;
case RACE_NET_SERVER_RANKINGS:
float prevpos, del;
if (prevpos) {
for (i=prevpos-1;i>pos-1;--i) {
grecordtime[i] = grecordtime[i-1];
- if(grecordholder[i])
- strunzone(grecordholder[i]);
- grecordholder[i] = strzone(grecordholder[i-1]);
+ strcpy(grecordholder[i], grecordholder[i-1]);
}
} else if (del) { // a record has been deleted by the admin
for (i=pos-1; i<= RANKINGS_CNT-1; ++i) {
if (i == RANKINGS_CNT-1) { // clear out last record
grecordtime[i] = 0;
- if (grecordholder[i])
- strunzone(grecordholder[i]);
- grecordholder[i] = string_null;
+ strfree(grecordholder[i]);
}
else {
grecordtime[i] = grecordtime[i+1];
- if (grecordholder[i])
- strunzone(grecordholder[i]);
- grecordholder[i] = strzone(grecordholder[i+1]);
+ strcpy(grecordholder[i], grecordholder[i+1]);
}
}
} else { // player has no ranked record yet
for (i=RANKINGS_CNT-1;i>pos-1;--i) {
grecordtime[i] = grecordtime[i-1];
- if(grecordholder[i])
- strunzone(grecordholder[i]);
- grecordholder[i] = strzone(grecordholder[i-1]);
+ strcpy(grecordholder[i], grecordholder[i-1]);
}
}
// store new ranking
- if(grecordholder[pos-1] != "")
- strunzone(grecordholder[pos-1]);
- grecordholder[pos-1] = strzone(ReadString());
+ strcpy(grecordholder[pos-1], ReadString());
grecordtime[pos-1] = ReadInt24_t();
if(strdecolorize(grecordholder[pos-1]) == strdecolorize(entcs_GetName(player_localnum)))
race_myrank = pos;
break;
case RACE_NET_SERVER_STATUS:
race_status = ReadShort();
- if(race_status_name)
- strunzone(race_status_name);
- race_status_name = strzone(ReadString());
+ strcpy(race_status_name, ReadString());
}
return true;
}
{
if(autocvar_accuracy_color_levels != acc_color_levels)
{
- if(acc_color_levels)
- strunzone(acc_color_levels);
- acc_color_levels = strzone(autocvar_accuracy_color_levels);
+ strcpy(acc_color_levels, autocvar_accuracy_color_levels);
acc_levels = tokenize_console(acc_color_levels);
if(acc_levels > MAX_ACCURACY_LEVELS)
acc_levels = MAX_ACCURACY_LEVELS;
#include <common/mutators/base.qh>
// register all possible hooks here
-
+
// to use a hook, first register your mutator using REGISTER_MUTATOR
// then create your function using MUTATOR_HOOKFUNCTION
.float v_angle_save_x;
-class(Skeleton) .float skeleton_info_modelindex;
-class(Skeleton) .float skeleton_info_skin;
+classfield(Skeleton) .float skeleton_info_modelindex;
+classfield(Skeleton) .float skeleton_info_skin;
const int BONETYPE_LOWER = 0;
const int BONETYPE_UPPER = 1;
const int MAX_BONES = 128;
-class(Skeleton) .float skeleton_bonetype[MAX_BONES];
-class(Skeleton) .float skeleton_numbones;
+classfield(Skeleton) .float skeleton_bonetype[MAX_BONES];
+classfield(Skeleton) .float skeleton_numbones;
void skeleton_loadinfo(entity e)
{
void skeleton_loadinfo(entity e);
entityclass(Skeleton);
-class(Skeleton) .float bone_upperbody;
-class(Skeleton) .int bone_weapon;
-class(Skeleton) .float bone_aim[MAX_AIM_BONES];
-class(Skeleton) .float bone_aimweight[MAX_AIM_BONES];
-class(Skeleton) .float fixbone;
+classfield(Skeleton) .float bone_upperbody;
+classfield(Skeleton) .int bone_weapon;
+classfield(Skeleton) .float bone_aim[MAX_AIM_BONES];
+classfield(Skeleton) .float bone_aimweight[MAX_AIM_BONES];
+classfield(Skeleton) .float fixbone;
#pragma once
entityclass(ShowNames);
-class(ShowNames) .float healthvalue;
-class(ShowNames) .float armorvalue;
-class(ShowNames) .float sameteam;
-class(ShowNames) .float fadedelay;
-class(ShowNames) .float pointtime;
+classfield(ShowNames) .float healthvalue;
+classfield(ShowNames) .float armorvalue;
+classfield(ShowNames) .float sameteam;
+classfield(ShowNames) .float fadedelay;
+classfield(ShowNames) .float pointtime;
void Draw_ShowNames_All();
entityclass(TeamRadar);
// to make entities have dots on the team radar
-class(TeamRadar) .float teamradar_icon;
-class(TeamRadar) .float teamradar_times[MAX_TEAMRADAR_TIMES];
-class(TeamRadar) .int teamradar_time_index;
-class(TeamRadar) .vector teamradar_color;
+classfield(TeamRadar) .float teamradar_icon;
+classfield(TeamRadar) .float teamradar_times[MAX_TEAMRADAR_TIMES];
+classfield(TeamRadar) .int teamradar_time_index;
+classfield(TeamRadar) .vector teamradar_color;
float teamradar_angle; // player yaw angle
vector teamradar_origin3d_in_texcoord; // player origin
wcross_scale_goal_prev = 0;
wcross_alpha_goal_prev = 0;
wcross_changedonetime = 0;
- if(wcross_name_goal_prev)
- strunzone(wcross_name_goal_prev);
- wcross_name_goal_prev = string_null;
- if(wcross_name_goal_prev_prev)
- strunzone(wcross_name_goal_prev_prev);
- wcross_name_goal_prev_prev = string_null;
+ strfree(wcross_name_goal_prev);
+ strfree(wcross_name_goal_prev_prev);
wcross_name_changestarttime = 0;
wcross_name_changedonetime = 0;
wcross_name_alpha_goal_prev = 0;
void Ent_Wall_Remove(entity this)
{
- if(this.bgmscript)
- strunzone(this.bgmscript);
- this.bgmscript = string_null;
+ strfree(this.bgmscript);
}
NET_HANDLE(ENT_CLIENT_WALL, bool isnew)
this.mins = this.maxs = '0 0 0';
setsize(this, this.mins, this.maxs);
- if(this.bgmscript)
- strunzone(this.bgmscript);
- this.bgmscript = ReadString();
- if(substring(this.bgmscript, 0, 1) == "<")
+ string s = ReadString();
+ if(substring(s, 0, 1) == "<")
{
- this.bgmscript = strzone(substring(this.bgmscript, 1, -1));
+ strcpy(this.bgmscript, substring(s, 1, -1));
this.bgmscriptangular = 1;
}
else
{
- this.bgmscript = strzone(this.bgmscript);
+ strcpy(this.bgmscript, s);
this.bgmscriptangular = 0;
}
if(this.bgmscript != "")
#pragma once
entityclass(Wall);
-class(Wall) .float lip;
-class(Wall) .float bgmscriptangular;
-class(Wall) .int lodmodelindex0, lodmodelindex1, lodmodelindex2;
-class(Wall) .float loddistance1, loddistance2;
-class(Wall) .vector saved;
+classfield(Wall) .float lip;
+classfield(Wall) .float bgmscriptangular;
+classfield(Wall) .int lodmodelindex0, lodmodelindex1, lodmodelindex2;
+classfield(Wall) .float loddistance1, loddistance2;
+classfield(Wall) .vector saved;
// Needed for interactive clientwalls
.float inactive; // Clientwall disappears when inactive
#include <common/sounds/sound.qh>
entityclass(Projectile);
-class(Projectile).int traileffect;
-
-class(Projectile).vector iorigin1, iorigin2;
-class(Projectile).float spawntime;
-class(Projectile).vector trail_oldorigin;
-class(Projectile).float trail_oldtime;
-class(Projectile).float fade_time, fade_rate;
-
-class(Projectile).float alphamod;
-class(Projectile).int count; // set if clientside projectile
-class(Projectile).int cnt; // sound index
-class(Projectile).float gravity;
-class(Projectile).int snd_looping;
-class(Projectile).bool silent;
+classfield(Projectile).int traileffect;
+
+classfield(Projectile).vector iorigin1, iorigin2;
+classfield(Projectile).float spawntime;
+classfield(Projectile).vector trail_oldorigin;
+classfield(Projectile).float trail_oldtime;
+classfield(Projectile).float fade_time, fade_rate;
+
+classfield(Projectile).float alphamod;
+classfield(Projectile).int count; // set if clientside projectile
+classfield(Projectile).int cnt; // sound index
+classfield(Projectile).float gravity;
+classfield(Projectile).int snd_looping;
+classfield(Projectile).bool silent;
void SUB_Stop(entity this, entity toucher);
{
if(campaign_title)
{
- strunzone(campaign_title);
+ strfree(campaign_title);
for(int i = 0; i < campaign_entries; ++i)
{
- strunzone(campaign_gametype[i]);
- strunzone(campaign_mapname[i]);
- strunzone(campaign_mutators[i]);
- strunzone(campaign_shortdesc[i]);
- strunzone(campaign_longdesc[i]);
+ strfree(campaign_gametype[i]);
+ strfree(campaign_mapname[i]);
+ strfree(campaign_mutators[i]);
+ strfree(campaign_shortdesc[i]);
+ strfree(campaign_longdesc[i]);
}
campaign_entries = 0;
- campaign_title = string_null;
}
}
}
DESTRUCTOR(DebugText3d) {
- strunzone(this.message);
+ strfree(this.message);
}
void DebugText3d_draw2d(DebugText3d this) {
#define EffectInfos_from(i) _EffectInfos_from(i, NULL)
REGISTER_REGISTRY(EffectInfos)
#define EFFECTINFO(name) \
- [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { } \
+ ACCUMULATE void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { } \
REGISTER(EffectInfos, EFFECTINFO, name, m_id, NEW(EffectInfoGroup)) { \
effectinfo_##name(this, NULL); \
}
#define MY(f) this.effectinfo_##f
#define DEF(name) EFFECTINFO(name)
#define SUB(name) \
- [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { parent = EFFECTINFO_##name; parent.children[parent.children_count++] = this = NEW(EffectInfo, #name); } \
- [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this)
+ ACCUMULATE void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { parent = EFFECTINFO_##name; parent.children[parent.children_count++] = this = NEW(EffectInfo, #name); } \
+ ACCUMULATE void effectinfo_##name(EffectInfoGroup parent, EffectInfo this)
#include "effectinfo.inc"
#undef MY
#undef DEF
#ifdef CSQC
entityclass(Casing);
-class(Casing) .float alpha;
-class(Casing) .bool silent;
-class(Casing) .int state;
-class(Casing) .float cnt;
+classfield(Casing) .float alpha;
+classfield(Casing) .bool silent;
+classfield(Casing) .int state;
+classfield(Casing) .float cnt;
void Casing_Delete(entity this)
{
.string fld = it.m_playersoundfld;
if (this.(fld))
{
- strunzone(this.(fld));
- this.(fld) = string_null;
+ strfree(this.(fld));
}
});
}
}
string file = argv(1);
string variants = argv(2);
- if (this.(field)) strunzone(this.(field));
- this.(field) = strzone(strcat(file, " ", variants));
+ strcpy(this.(field), strcat(file, " ", variants));
}
fclose(fh);
return true;
void UpdatePlayerSounds(entity this)
{
if (this.model == this.model_for_playersound && this.skin == this.skin_for_playersound) return;
- if (this.model_for_playersound) strunzone(this.model_for_playersound);
- this.model_for_playersound = strzone(this.model);
+ strcpy(this.model_for_playersound, this.model);
this.skin_for_playersound = this.skin;
ClearPlayerSounds(this);
LoadPlayerSounds(this, "sound/player/default.sounds", true);
#ifdef CSQC
entityclass(ModelEffect);
-class(ModelEffect) .float frame1time;
-class(ModelEffect) .float lifetime, fadetime;
-class(ModelEffect) .float teleport_time;
-class(ModelEffect) .float scale1, scale2;
+classfield(ModelEffect) .float frame1time;
+classfield(ModelEffect) .float lifetime, fadetime;
+classfield(ModelEffect) .float teleport_time;
+classfield(ModelEffect) .float scale1, scale2;
.float cnt;
.float scale;
#ifdef CSQC
entityclass(Rubble);
-class(Rubble).float creationtime;
+classfield(Rubble).float creationtime;
IntrusiveList g_rubble;
STATIC_INIT(g_rubble) { g_rubble = IL_NEW(); }
/** the engine player name strings are mutable! */
#define ENTCS_SET_MUTABLE_STRING(var, x) MACRO_BEGIN \
- if (var) strunzone(var); \
- var = strzone(x); \
+ strcpy(var, x); \
MACRO_END
ENTCS_PROP(ENTNUM, false, sv_entnum, ENTCS_SET_NORMAL, {}, {}) /* sentinel */
ENTCS_PROP(NAME, true, netname, ENTCS_SET_MUTABLE_STRING,
{ WriteString(chan, ent.netname); },
- { if (ent.netname) strunzone(ent.netname); ent.netname = strzone(ReadString()); })
+ { strcpy(ent.netname, ReadString()); })
ENTCS_PROP(MODEL, true, model, ENTCS_SET_NORMAL,
{ WriteString(chan, ent.model); },
- { if (ent.model) strunzone(ent.model); ent.model = strzone(ReadString()); })
+ { strcpy(ent.model, ReadString()); })
ENTCS_PROP(SKIN, true, skin, ENTCS_SET_NORMAL,
{ WriteByte(chan, ent.skin); },
int n = this.sv_entnum;
entity e = entcs_receiver(n);
entcs_receiver(n, NULL);
- if (e.netname) strunzone(e.netname);
- e.netname = string_null;
- if (e.model) strunzone(e.model);
- e.model = string_null;
+ strfree(e.netname);
+ strfree(e.model);
if (e != this) delete(e);
}
// `cl_forceplayermodels 1` sounds will be wrong until the player has been in the PVS, but so be it
if (this.model != e.model)
{
- if (this.model) strunzone(this.model);
- this.model = strzone(e.model);
+ strcpy(this.model, e.model);
}
}
case BD_TILE_BRICK1: return false;
}
- if(hit.netname) { strunzone(hit.netname); }
- hit.netname = strzone(testpos);
+ strcpy(hit.netname, testpos);
minigame_server_sendflags(hit,MINIG_SF_UPDATE);
break;
}
case BD_TILE_BRICK1: return false;
}
- if(dozer.netname) { strunzone(dozer.netname); }
- dozer.netname = strzone(newpos);
+ strcpy(dozer.netname, newpos);
return true;
}
if(!piece)
return; // how?!
- if(piece.netname) { strunzone(piece.netname); }
+ strfree(piece.netname);
delete(piece);
minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
return;
if(targ && thetype == targ.bd_tiletype)
{
- if(targ.netname) { strunzone(targ.netname); }
+ strfree(targ.netname);
delete(targ);
}
else if(piece && thetype == piece.bd_tiletype)
{
- if(piece.netname) { strunzone(piece.netname); }
+ strfree(piece.netname);
delete(piece);
}
else return;
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
e = NULL;
if(minigame.bd_nextlevel && minigame.bd_nextlevel != "")
{
- if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
- minigame.bd_levelname = strzone(minigame.bd_nextlevel);
+ strcpy(minigame.bd_levelname, minigame.bd_nextlevel);
}
bd_setup_pieces(minigame);
void bd_set_next_match(entity minigame, string next)
{
- if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
- minigame.bd_nextlevel = strzone(next);
+ strcpy(minigame.bd_nextlevel, next);
}
void bd_next_match(entity minigame, entity player, string next)
{
tokenize_console(s);
- if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
- minigame.bd_nextlevel = strzone(argv(2));
+ strcpy(minigame.bd_nextlevel, argv(2));
}
int bd_fix_dir(vector dir)
{
case "start":
{
- if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
- minigame.bd_levelname = strzone(autocvar_sv_minigames_bulldozer_startlevel);
+ strcpy(minigame.bd_levelname, autocvar_sv_minigames_bulldozer_startlevel);
bd_setup_pieces(minigame);
minigame.minigame_flags = BD_TURN_MOVE;
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
e = NULL;
delete(e);
}
- if(minigame.bd_nextlevel) { strunzone(minigame.bd_nextlevel); }
- if(minigame.bd_levelname) { strunzone(minigame.bd_levelname); }
+ strfree(minigame.bd_nextlevel);
+ strfree(minigame.bd_levelname);
return false;
}
case "join":
void bd_set_curr_pos(string s)
{
- if ( bd_curr_pos )
- strunzone(bd_curr_pos);
+ strfree(bd_curr_pos);
if ( s )
s = strzone(s);
bd_curr_pos = s;
{
int letter = ReadByte();
int number = ReadByte();
- if(sent.netname) { strunzone(sent.netname); }
- sent.netname = strzone(minigame_tile_buildname(letter, number));
+ strcpy(sent.netname, minigame_tile_buildname(letter, number));
sent.bd_tiletype = ReadByte();
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
return false;
void c4_set_curr_pos(string s)
{
- if ( c4_curr_pos )
- strunzone(c4_curr_pos);
+ strfree(c4_curr_pos);
if ( s )
s = strzone(s);
c4_curr_pos = s;
while ( ( e = findentity(e,owner,minig) ) )
if ( e.classname == "minigame_nmm_tile" )
{
- strunzone(e.netname);
- strunzone(e.nmm_tile_hmill);
- strunzone(e.nmm_tile_vmill);
+ strfree(e.netname);
+ strfree(e.nmm_tile_hmill);
+ strfree(e.nmm_tile_vmill);
delete(e);
}
}
if(existing)
{
- if(existing.netname) { strunzone(existing.netname); }
+ strfree(existing.netname);
delete(existing);
}
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
return false;
void pp_set_curr_pos(string s)
{
- if ( pp_curr_pos )
- strunzone(pp_curr_pos);
+ strfree(pp_curr_pos);
if ( s )
s = strzone(s);
pp_curr_pos = s;
if(!middle)
return false;
- if(middle.netname) { strunzone(middle.netname); }
+ strfree(middle.netname);
delete(middle);
- if(piece.netname) { strunzone(piece.netname); }
- piece.netname = strzone(pos);
+ strcpy(piece.netname, pos);
minigame_server_sendflags(piece,MINIG_SF_ALL);
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
return false;
void ps_set_curr_pos(string s)
{
- if ( ps_curr_pos )
- strunzone(ps_curr_pos);
+ strfree(ps_curr_pos);
if ( s )
s = strzone(s);
ps_curr_pos = s;
while( (e = findentity(e, owner, minigame)) )
if(e.classname == "minigame_board_piece")
{
- if(e.netname) { strunzone(e.netname); }
+ strfree(e.netname);
delete(e);
}
return false;
void ttt_set_curr_pos(string s)
{
- if ( ttt_curr_pos )
- strunzone(ttt_curr_pos);
+ strfree(ttt_curr_pos);
if ( s )
s = strzone(s);
ttt_curr_pos = s;
delete(e);
}
- strunzone(minigame_session.netname);
+ strfree(minigame_session.netname);
delete(minigame_session);
}
#pragma once
-#define setmodel(e, m) _setmodel((e), (m).model_str())
-
CLASS(Model, Object)
ATTRIB(Model, m_id, int, 0);
ATTRIB(Model, model_str, string());
+ ATTRIB(Model, model_str_, string);
CONSTRUCTOR(Model, string() path)
{
CONSTRUCT(Model);
}
profile(sprintf("precache_model(\"%s\")", s));
precache_model(s);
+ strcpy(this.model_str_, s);
}
ENDCLASS(Model)
+
+#define setmodel(this, m) MACRO_BEGIN \
+ Model _setmodel_model = (m); \
+ string _setmodel_cached = _setmodel_model.model_str_; \
+ _setmodel((this), _setmodel_cached ? _setmodel_cached : _setmodel_model.model_str()); \
+MACRO_END
void Monster_Sounds_Clear(entity this)
{
-#define _MSOUND(m) if(this.monstersound_##m) { strunzone(this.monstersound_##m); this.monstersound_##m = string_null; }
+#define _MSOUND(m) strfree(this.monstersound_##m);
ALLMONSTERSOUNDS
#undef _MSOUND
}
field = Monster_Sound_SampleField(argv(0));
if(GetMonsterSoundSampleField_notFound)
continue;
- if (this.(field))
- strunzone(this.(field));
- this.(field) = strzone(strcat(argv(1), " ", argv(2)));
+ strcpy(this.(field), strcat(argv(1), " ", argv(2)));
}
fclose(fh);
return true;
if(monster == "random" || allow_any)
{
RandomSelection_Init();
- FOREACH(Monsters, it != MON_Null && (allow_any || (!(it.spawnflags & MONSTER_TYPE_PASSIVE) && !(it.spawnflags & MON_FLAG_HIDDEN))),
+ FOREACH(Monsters, it != MON_Null && (allow_any || !(it.spawnflags & MON_FLAG_HIDDEN)) && !(it.spawnflags & MONSTER_TYPE_PASSIVE),
{
RandomSelection_AddEnt(it, 1, 1);
});
params(_MUTATOR_HANDLE_NOP, _MUTATOR_HANDLE_POPOUT) \
return ret; \
} \
- [[accumulate]] void RegisterHooks() { HOOK_##id = NEW(CallbackChain, #id); }
+ ACCUMULATE void RegisterHooks() { HOOK_##id = NEW(CallbackChain, #id); }
#define MUTATOR_CALLHOOK(id, ...) _MUTATOR_CALLHOOK(id, __VA_ARGS__)
#ifdef __STDC__
bool MUTATOR_##id##_check() { return dependence; } \
REGISTER(Mutators, MUTATOR, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
{ this.mutatorcheck = MUTATOR_##id##_check; } \
- [[accumulate]] bool MUTATORFUNCTION_##id(int mode)
+ ACCUMULATE bool MUTATORFUNCTION_##id(int mode)
STATIC_INIT(Mutators) {
RegisterHooks();
#define _MUTATOR_CALLBACK(name, func) \
Callback CALLBACK_##name; \
bool func(); \
- [[accumulate]] void RegisterCallbacks() { CALLBACK_##name = NEW(Callback, func); }
+ ACCUMULATE void RegisterCallbacks() { CALLBACK_##name = NEW(Callback, func); }
#define MUTATOR_HOOKFUNCTION(...) \
EVAL_MUTATOR_HOOKFUNCTION(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
#define MUTATOR_HOOKFUNCTION_3(mut, cb, order) \
_MUTATOR_CALLBACK(mut##_##cb, mut##_##cb) \
- [[accumulate]] bool MUTATORFUNCTION_##mut##_hooks(int mode) { MUTATOR_HOOK(cb, mut##_##cb, order); } \
+ ACCUMULATE bool MUTATORFUNCTION_##mut##_hooks(int mode) { MUTATOR_HOOK(cb, mut##_##cb, order); } \
bool mut##_##cb() { return = false; } \
- [[accumulate]] bool mut##_##cb()
+ ACCUMULATE bool mut##_##cb()
#define MUTATOR_HOOK(cb, func, order) MACRO_BEGIN { \
MUTATOR_ONADD { \
BUFF_ONADD(BUFF_INVISIBLE)
{
- if(time < player.strength_finished && g_instagib)
+ if(time < player.strength_finished && autocvar_g_instagib)
player.buff_invisible_prev_alpha = default_player_alpha; // we don't want to save the powerup's alpha, as player may lose the powerup while holding the buff
else
player.buff_invisible_prev_alpha = player.alpha;
BUFF_ONREM(BUFF_INVISIBLE)
{
- if(time < player.strength_finished && g_instagib)
+ if(time < player.strength_finished && autocvar_g_instagib)
player.alpha = autocvar_g_instagib_invis_alpha;
else
player.alpha = player.buff_invisible_prev_alpha;
#include "sv_cloaked.qh"
-string autocvar_g_cloaked;
-REGISTER_MUTATOR(cloaked, expr_evaluate(autocvar_g_cloaked));
+//string autocvar_g_cloaked;
+REGISTER_MUTATOR(cloaked, expr_evaluate(cvar_string("g_cloaked")));
float autocvar_g_balance_cloaked_alpha;
);
}
- if (this.text) strunzone(this.text);
- this.text = strzone(s);
+ strcpy(this.text, s);
this.m_size = map_bound_ranges(potential,
autocvar_cl_damagetext_size_min_damage, autocvar_cl_damagetext_size_max_damage,
}
DESTRUCTOR(DamageText) {
- if (this.text) strunzone(this.text);
+ strfree(this.text);
if (this == DamageText_screen_first) {
// start from 0 offset again, hopefully, others (if any) will have faded away by now
DamageText_screen_first = NULL;
#include "sv_melee_only.qh"
string autocvar_g_melee_only;
-REGISTER_MUTATOR(melee_only, expr_evaluate(autocvar_g_melee_only) && !cvar("g_instagib") && !cvar("g_overkill") && !g_nexball);
+REGISTER_MUTATOR(melee_only, expr_evaluate(autocvar_g_melee_only) && !autocvar_g_instagib && !cvar("g_overkill") && !g_nexball);
MUTATOR_HOOKFUNCTION(melee_only, SetStartItems, CBC_ORDER_LAST)
{
*/
-string autocvar_g_new_toys;
+//string autocvar_g_new_toys;
bool nt_IsNewToy(int w);
-REGISTER_MUTATOR(nt, expr_evaluate(autocvar_g_new_toys) && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nt, expr_evaluate(cvar_string("g_new_toys")) && !autocvar_g_instagib && !cvar("g_overkill"))
{
MUTATOR_ONADD
{
#include "sv_nix.qh"
-string autocvar_g_nix;
+//string autocvar_g_nix;
int autocvar_g_balance_nix_ammo_cells;
int autocvar_g_balance_nix_ammo_plasma;
int autocvar_g_balance_nix_ammo_fuel;
bool NIX_CanChooseWeapon(int wpn);
-REGISTER_MUTATOR(nix, expr_evaluate(autocvar_g_nix) && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nix, expr_evaluate(cvar_string("g_nix")) && !autocvar_g_instagib && !cvar("g_overkill"))
{
MUTATOR_ONADD
{
.Weapon ok_lastwep[MAX_WEAPONSLOTS];
-REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !cvar("g_instagib") && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
+REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !autocvar_g_instagib && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
{
MUTATOR_ONADD
{
#include "sv_pinata.qh"
string autocvar_g_pinata;
-REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !cvar("g_instagib") && !cvar("g_overkill"));
+REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !autocvar_g_instagib && !cvar("g_overkill"));
MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
{
#include <common/deathtypes/all.qh>
#include <server/round_handler.qh>
-REGISTER_MUTATOR(rm, cvar("g_instagib"));
+REGISTER_MUTATOR(rm, autocvar_g_instagib);
MUTATOR_HOOKFUNCTION(rm, Damage_Calculate)
{
// if the object being removed has been selected for attachment by a player, unset it
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.object_attach == e, { it.object_attach = NULL; });
- if(e.material) { strunzone(e.material); e.material = string_null; }
- if(e.crypto_idfp) { strunzone(e.crypto_idfp); e.crypto_idfp = string_null; }
- if(e.netname) { strunzone(e.netname); e.netname = string_null; }
- if(e.message) { strunzone(e.message); e.message = string_null; }
- if(e.message2) { strunzone(e.message2); e.message2 = string_null; }
+ strfree(e.material);
+ strfree(e.crypto_idfp);
+ strfree(e.netname);
+ strfree(e.message);
+ strfree(e.message2);
delete(e);
e = NULL;
e.old_movetype = stof(argv(argv_num)); ++argv_num;
set_movetype(e, e.old_movetype);
e.damageforcescale = stof(argv(argv_num)); ++argv_num;
- if(e.material) strunzone(e.material); if(argv(argv_num) != "") e.material = strzone(argv(argv_num)); else e.material = string_null; ++argv_num;
+ strfree(e.material); if(argv(argv_num) != "") e.material = strzone(argv(argv_num)); else e.material = string_null; ++argv_num;
if(database)
{
// properties stored only for the database
- if(e.crypto_idfp) strunzone(e.crypto_idfp); if(argv(argv_num) != "") e.crypto_idfp = strzone(argv(argv_num)); else e.crypto_idfp = string_null; ++argv_num;
- if(e.netname) strunzone(e.netname); e.netname = strzone(argv(argv_num)); ++argv_num;
- if(e.message) strunzone(e.message); e.message = strzone(argv(argv_num)); ++argv_num;
- if(e.message2) strunzone(e.message2); e.message2 = strzone(argv(argv_num)); ++argv_num;
+ strfree(e.crypto_idfp); if(argv(argv_num) != "") e.crypto_idfp = strzone(argv(argv_num)); else e.crypto_idfp = string_null; ++argv_num;
+ strcpy(e.netname, argv(argv_num)); ++argv_num;
+ strcpy(e.message, argv(argv_num)); ++argv_num;
+ strcpy(e.message2, argv(argv_num)); ++argv_num;
}
// attach last
e.damageforcescale = stof(argv(3));
break;
case "material":
- if(e.material) strunzone(e.material);
+ strfree(e.material);
if(argv(3))
{
for (j = 1; j <= 5; j++) // precache material sounds, 5 in total
}
// update last editing time
- if(e.message2) strunzone(e.message2);
- e.message2 = strzone(strftime(true, "%d-%m-%Y %H:%M:%S"));
+ strcpy(e.message2, strftime(true, "%d-%m-%Y %H:%M:%S"));
if(autocvar_g_sandbox_info > 1)
LOG_INFO("^3SANDBOX - SERVER: ^7", player.netname, " edited property ^3", argv(2), " ^7of an object at origin ^3", vtos(e.origin));
// also update the player's nickname if he changed it (but has the same player UID)
if(e.netname != player.netname)
{
- if(e.netname) strunzone(e.netname);
- e.netname = strzone(player.netname);
+ strcpy(e.netname, player.netname);
print_to(player, "^2SANDBOX - INFO: ^7Object owner name updated");
}
return true;
}
- if(e.crypto_idfp) strunzone(e.crypto_idfp);
- e.crypto_idfp = strzone(player.crypto_idfp);
+ strcpy(e.crypto_idfp, player.crypto_idfp);
print_to(player, "^2SANDBOX - INFO: ^7Object claimed successfully");
}
#include "sv_vampire.qh"
string autocvar_g_vampire;
-REGISTER_MUTATOR(vampire, expr_evaluate(autocvar_g_vampire) && !cvar("g_instagib"));
+REGISTER_MUTATOR(vampire, expr_evaluate(autocvar_g_vampire) && !autocvar_g_instagib);
MUTATOR_HOOKFUNCTION(vampire, PlayerDamage_SplitHealthArmor)
{
void Ent_RemoveWaypointSprite(entity this)
{
- if (this.netname) strunzone(this.netname);
- if (this.netname2) strunzone(this.netname2);
- if (this.netname3) strunzone(this.netname3);
+ strfree(this.netname);
+ strfree(this.netname2);
+ strfree(this.netname3);
}
/** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
if (sendflags & 2)
{
- if (this.netname)
- strunzone(this.netname);
- this.netname = strzone(ReadString());
+ strcpy(this.netname, ReadString());
}
if (sendflags & 4)
{
- if (this.netname2)
- strunzone(this.netname2);
- this.netname2 = strzone(ReadString());
+ strcpy(this.netname2, ReadString());
}
if (sendflags & 8)
{
- if (this.netname3)
- strunzone(this.netname3);
- this.netname3 = strzone(ReadString());
+ strcpy(this.netname3, ReadString());
}
if (sendflags & 16)
#ifdef CSQC
entityclass(WaypointSprite);
-class(WaypointSprite) .float helpme;
-class(WaypointSprite) .float rule;
-class(WaypointSprite) .string netname; // primary picture
-class(WaypointSprite) .string netname2; // secondary picture
-class(WaypointSprite) .string netname3; // tertiary picture
-class(WaypointSprite) .int team; // team that gets netname2
-class(WaypointSprite) .float lifetime;
-class(WaypointSprite) .float fadetime;
-class(WaypointSprite) .float maxdistance;
-class(WaypointSprite) .int hideflags;
-class(WaypointSprite) .float spawntime;
-class(WaypointSprite) .float health;
-class(WaypointSprite) .float build_started;
-class(WaypointSprite) .float build_starthealth;
-class(WaypointSprite) .float build_finished;
+classfield(WaypointSprite) .float helpme;
+classfield(WaypointSprite) .float rule;
+classfield(WaypointSprite) .string netname; // primary picture
+classfield(WaypointSprite) .string netname2; // secondary picture
+classfield(WaypointSprite) .string netname3; // tertiary picture
+classfield(WaypointSprite) .int team; // team that gets netname2
+classfield(WaypointSprite) .float lifetime;
+classfield(WaypointSprite) .float fadetime;
+classfield(WaypointSprite) .float maxdistance;
+classfield(WaypointSprite) .int hideflags;
+classfield(WaypointSprite) .float spawntime;
+classfield(WaypointSprite) .float health;
+classfield(WaypointSprite) .float build_started;
+classfield(WaypointSprite) .float build_starthealth;
+classfield(WaypointSprite) .float build_finished;
float autocvar_g_waypointsprite_alpha;
float autocvar_g_waypointsprite_crosshairfadealpha;
_sound(NULL, soundchannel, AnnouncerFilename(soundfile), soundvolume, soundposition);
- if (prev_soundfile) strunzone(prev_soundfile);
- prev_soundfile = strzone(soundfile);
+ strcpy(prev_soundfile, soundfile);
prev_soundtime = time;
}
else
this.owner.nent_name
));
#endif
- for (int i = 0; i < this.nent_stringcount; ++i) { if (this.nent_strings[i]) strunzone(this.nent_strings[i]); }
+ for (int i = 0; i < this.nent_stringcount; ++i) { strfree(this.nent_strings[i]); }
delete(this);
}
void PM_ClientMovement_UpdateStatus(entity this)
{
-#ifdef CSQC
if(!IS_PLAYER(this))
return;
- // set crouched
- bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+ bool have_hook = false;
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- entity wep = viewmodels[slot];
- if(wep.hook && !wasfreed(wep.hook))
+ #if defined(CSQC)
+ entity wepent = viewmodels[slot];
+ #elif defined(SVQC)
+ .entity weaponentity = weaponentities[slot];
+ entity wepent = this.(weaponentity);
+ #endif
+ if(wepent.hook && !wasfreed(wepent.hook))
{
- do_crouch = false;
- break; // don't bother checking the others
+ have_hook = true;
+ break;
}
}
- //if(this.waterlevel >= WATERLEVEL_SWIMMING)
+ bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+ if (have_hook) {
+ do_crouch = false;
+ //} else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
//do_crouch = false;
- if(hud != HUD_NORMAL)
+ } else if (PHYS_INVEHICLE(this)) {
do_crouch = false;
- if(STAT(FROZEN, this))
+ } else if (STAT(FROZEN, this)) {
do_crouch = false;
+ }
- if (do_crouch)
- {
- // wants to crouch, this always works
- if (!IS_DUCKED(this)) SET_DUCKED(this);
- }
- else
- {
- // wants to stand, if currently crouching we need to check for a low ceiling first
- if (IS_DUCKED(this))
- {
- tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, MOVE_NORMAL, this);
- if (!trace_startsolid) UNSET_DUCKED(this);
+ if (do_crouch) {
+ if (!IS_DUCKED(this)) {
+ SET_DUCKED(this);
+ this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
+ setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
+ // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
}
+ } else if (IS_DUCKED(this)) {
+ tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
+ if (!trace_startsolid) {
+ UNSET_DUCKED(this);
+ this.view_ofs = STAT(PL_VIEW_OFS, this);
+ setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
+ }
}
+#ifdef CSQC
if (IS_ONGROUND(this) || this.velocity.z <= 0 || PHYS_WATERJUMP_TIME(this) <= 0)
PHYS_WATERJUMP_TIME(this) = 0;
#define SET_DUCKED(s) ((s).flags |= FL_DUCKED)
#define UNSET_DUCKED(s) ((s).flags &= ~FL_DUCKED)
+ #define PHYS_INVEHICLE(s) (boolean(hud != HUD_NORMAL))
+
#define PHYS_JUMPSPEEDCAP_MIN autocvar_cl_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_cl_jumpspeedcap_max
#define SET_DUCKED(s) ((s).crouch = true)
#define UNSET_DUCKED(s) ((s).crouch = false)
+ #define PHYS_INVEHICLE(s) (boolean((s).vehicle != NULL))
+
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
}
}
- strunzone(p.playerstats_id);
- p.playerstats_id = string_null;
+ strfree(p.playerstats_id);
}
void PlayerStats_GameReport(float finished)
// const int CH_BGM_SINGLE = -8;
const int CH_BGM_SINGLE = 8;
const int CH_AMBIENT = -9;
-// const int CH_AMBIENT_SINGLE = 9;
+const int CH_AMBIENT_SINGLE = 9;
const float ATTEN_NONE = 0;
const float ATTEN_MIN = 0.015625;
} \
} MACRO_END
+string _Sound_fixpath(string base)
+{
+ if (base == "") return string_null;
+#ifdef SVQC
+ return strcat(base, ".wav"); // let the client engine decide
+#else
+#define extensions(x) \
+ x(wav) \
+ x(ogg) \
+ x(flac) \
+ /**/
+#define tryext(ext) { \
+ string s = strcat(base, "." #ext); \
+ if (fexists(strcat("sound/", s))) { \
+ return s; \
+ } \
+ }
+ extensions(tryext);
+ LOG_WARNF("Missing sound: \"%s\"", strcat("sound/", base));
+#undef tryext
+#undef extensions
+ return string_null;
+#endif
+}
+
CLASS(Sound, Object)
ATTRIB(Sound, m_id, int, 0);
ATTRIB(Sound, sound_str, string());
+ ATTRIB(Sound, sound_str_, string);
CONSTRUCTOR(Sound, string() path)
{
CONSTRUCT(Sound);
this.sound_str = path;
}
- #define Sound_fixpath(this) _Sound_fixpath((this).sound_str())
- string _Sound_fixpath(string base)
- {
- if (base == "") return string_null;
-#ifdef SVQC
- return strcat(base, ".wav"); // let the client engine decide
-#else
- #define extensions(x) \
- x(wav) \
- x(ogg) \
- x(flac) \
- /**/
- #define tryext(ext) { string s = strcat(base, "." #ext); if (fexists(strcat("sound/", s))) return s; }
- extensions(tryext);
- LOG_WARNF("Missing sound: \"%s\"", strcat("sound/", base));
- #undef tryext
- #undef extensions
- return string_null;
-#endif
- }
METHOD(Sound, sound_precache, void(Sound this))
{
TC(Sound, this);
- string s = Sound_fixpath(this);
+ string s = _Sound_fixpath(this.sound_str());
if (!s) return;
profile(sprintf("precache_sound(\"%s\")", s));
precache_sound(s);
+ strcpy(this.sound_str_, s);
}
ENDCLASS(Sound)
+
+entity _Sound_fixpath_this;
+string _Sound_fixpath_cached;
+#define Sound_fixpath(this) ( \
+ _Sound_fixpath_this = (this), \
+ _Sound_fixpath_cached = _Sound_fixpath_this.sound_str_, \
+ _Sound_fixpath_cached ? _Sound_fixpath_cached : _Sound_fixpath(_Sound_fixpath_this.sound_str()) \
+)
void ItemRemove(entity this)
{
- if(this.mdl)
- strunzone(this.mdl);
+ strfree(this.mdl);
+}
+
+HashMap ENT_CLIENT_ITEM_simple;
+STATIC_INIT(ENT_CLIENT_ITEM_simple)
+{
+ HM_NEW(ENT_CLIENT_ITEM_simple);
+}
+SHUTDOWN(ENT_CLIENT_ITEM_simple)
+{
+ HM_DELETE(ENT_CLIENT_ITEM_simple);
}
NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade)
setpredraw(this, Item_PreDraw);
- if(this.mdl)
- strunzone(this.mdl);
+ strfree(this.mdl);
- this.mdl = "";
string _fn = ReadString();
this.item_simple = false; // reset it!
string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
this.item_simple = true;
- if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3")))
- this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".md3"));
- else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".dpm")))
- this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".dpm"));
- else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".iqm")))
- this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".iqm"));
- else if(fexists(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".mdl")))
- this.mdl = strzone(strcat(_fn2, autocvar_cl_simpleitems_postfix, ".mdl"));
- else
- {
- this.item_simple = false;
- LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
- }
+ #define extensions(x) \
+ x(md3) \
+ x(dpm) \
+ x(iqm) \
+ x(mdl) \
+ /**/
+ #define tryext(ext) { \
+ string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
+ string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
+ if (cached == "") { \
+ HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
+ } \
+ if (cached != "0") { \
+ strcpy(this.mdl, s); \
+ break; \
+ } \
+ }
+ do {
+ extensions(tryext);
+ this.item_simple = false;
+ LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
+ } while (0);
+ #undef tryext
+ #undef extensions
}
if(!this.item_simple)
- this.mdl = strzone(_fn);
-
+ strcpy(this.mdl, _fn);
if(this.mdl == "")
- LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!");
+ LOG_WARNF("this.mdl is unset for item %s", this.classname);
precache_model(this.mdl);
_setmodel(this, this.mdl);
--- /dev/null
+#pragma once
+
+//-----------
+// SPAWNFLAGS
+//-----------
+const int START_ENABLED = BIT(0);
+const int START_DISABLED = BIT(0);
+const int ALL_ENTITIES = BIT(1);
+const int ON_MAPLOAD = BIT(1);
+const int INVERT_TEAMS = BIT(2);
+const int CRUSH = BIT(2);
+const int NOSPLASH = BIT(8); // generic anti-splashdamage spawnflag
+const int ONLY_PLAYERS = BIT(14);
+
+// triggers
+const int SPAWNFLAG_NOMESSAGE = BIT(0);
+const int SPAWNFLAG_NOTOUCH = BIT(0);
+
+//----------
+// SENDFLAGS
+//----------
+const int SF_TRIGGER_INIT = BIT(0);
+const int SF_TRIGGER_UPDATE = BIT(1);
+const int SF_TRIGGER_RESET = BIT(2);
+
+//----------------
+// STATES & ACTIVE
+//----------------
+#ifdef CSQC
+// this stuff is defined in the server side engine VM, so we must define it separately here
+const int STATE_TOP = 0;
+const int STATE_BOTTOM = 1;
+const int STATE_UP = 2;
+const int STATE_DOWN = 3;
+
+const int ACTIVE_NOT = 0;
+const int ACTIVE_ACTIVE = 1;
+const int ACTIVE_IDLE = 2;
+const int ACTIVE_BUSY = 2;
+const int ACTIVE_TOGGLE = 3;
+#endif
this.dmgtime2 = time;
// how far to bob
- if (this.spawnflags & 1) // X
+ if (this.spawnflags & BOBBING_XAXIS)
this.movedir = '1 0 0' * this.height;
- else if (this.spawnflags & 2) // Y
+ else if (this.spawnflags & BOBBING_YAXIS)
this.movedir = '0 1 0' * this.height;
else // Z
this.movedir = '0 0 1' * this.height;
#pragma once
+
+
+const int BOBBING_XAXIS = BIT(0);
+const int BOBBING_YAXIS = BIT(1);
// target = targets to trigger when broken
// health = amount of damage it can take
// spawnflags:
-// 1 = start disabled (needs to be triggered to activate)
-// 2 = indicate damage
-// 4 = don't take direct damage (needs to be triggered to 'explode', then triggered again to restore)
+// START_DISABLED: needs to be triggered to activate
+// BREAKABLE_INDICATE_DAMAGE: indicate damage
+// BREAKABLE_NODAMAGE: don't take direct damage (needs to be triggered to 'explode', then triggered again to restore)
+// NOSPLASH: don't take splash damage
// notes:
// for mdl_dead to work, origin must be set (using a common/origin brush).
// Otherwise mdl_dead will be displayed at the map origin, and nobody would
void func_breakable_colormod(entity this)
{
float h;
- if (!(this.spawnflags & 2))
+ if (!(this.spawnflags & BREAKABLE_INDICATE_DAMAGE))
return;
h = this.health / this.max_health;
if(h < 0.25)
IL_REMOVE(g_bot_targets, this);
this.bot_attack = false;
this.event_damage = func_null;
- this.state = 1;
- if(this.spawnflags & 4)
+ this.state = STATE_BROKEN;
+ if(this.spawnflags & BREAKABLE_NODAMAGE)
this.use = func_null;
func_breakable_colormod(this);
if (this.noise1)
WaypointSprite_UpdateMaxHealth(this.sprite, this.max_health);
WaypointSprite_UpdateHealth(this.sprite, this.health);
}
- if(!(this.spawnflags & 4))
+ if(!(this.spawnflags & BREAKABLE_NODAMAGE))
{
this.takedamage = DAMAGE_AIM;
if(!this.bot_attack)
this.bot_attack = true;
this.event_damage = func_breakable_damage;
}
- if(this.spawnflags & 4)
+ if(this.spawnflags & BREAKABLE_NODAMAGE)
this.use = func_breakable_destroy; // don't need to set it usually, as .use isn't reset
- this.state = 0;
+ this.state = STATE_ALIVE;
//this.nextthink = 0; // cancel auto respawn
setthink(this, func_breakable_think);
this.nextthink = time + 0.1;
void func_breakable_init_for_player(entity this, entity player)
{
- if (this.noise1 && this.state == 0 && IS_REAL_CLIENT(player))
+ if (this.noise1 && this.state == STATE_ALIVE && IS_REAL_CLIENT(player))
{
msg_entity = player;
soundto (MSG_ONE, this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
void func_breakable_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
- if(this.state == 1)
+ if(this.state == STATE_BROKEN)
return;
- if(this.spawnflags & DOOR_NOSPLASH)
+ if(this.spawnflags & NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
if(this.team)
{
this.team = this.team_saved;
func_breakable_look_restore(this);
- if(this.spawnflags & 1)
+ if(this.spawnflags & START_DISABLED)
func_breakable_behave_destroyed(this);
else
func_breakable_behave_restore(this);
this.mdl = this.model;
SetBrushEntityModel(this);
- if(this.spawnflags & 4)
+ if(this.spawnflags & BREAKABLE_NODAMAGE)
this.use = func_breakable_destroy;
else
this.use = func_breakable_restore;
- if(this.spawnflags & 4)
+ if(this.spawnflags & BREAKABLE_NODAMAGE)
{
this.takedamage = DAMAGE_NO;
this.event_damage = func_null;
#pragma once
+
+const int BREAKABLE_INDICATE_DAMAGE = BIT(1);
+const int BREAKABLE_NODAMAGE = BIT(2);
+
+const int STATE_ALIVE = 0;
+const int STATE_BROKEN = 1;
+
#ifdef SVQC
spawnfunc(func_breakable);
#endif
void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
- if(this.spawnflags & DOOR_NOSPLASH)
+ if(this.spawnflags & NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
if (this.spawnflags & BUTTON_DONTACCUMULATEDMG)
"wait" override the default 1 second wait (-1 = never return)
"lip" override the default 4 pixel lip remaining at end of move
"health" if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser
-"sounds"
-0) steam metal
-1) wooden clunk
-2) metallic click
-3) in-out
+"noise" sound that is played when the button is activated
*/
spawnfunc(func_button)
{
#pragma once
-const int BUTTON_DONTACCUMULATEDMG = 128;
+
+const int BUTTON_DONTACCUMULATEDMG = BIT(7);
IL_REMOVE(g_conveyed, it);
});
- if(this.state)
+ if(this.active == ACTIVE_ACTIVE)
{
- FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, !it.conveyor.state && isPushable(it),
+ FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, it.conveyor.active == ACTIVE_NOT && isPushable(it),
{
vector emin = it.absmin;
vector emax = it.absmax;
#ifdef SVQC
-void conveyor_use(entity this, entity actor, entity trigger)
-{
- this.state = !this.state;
-
- this.SendFlags |= 2;
-}
-
-void conveyor_reset(entity this)
-{
- this.state = (this.spawnflags & 1);
-
- this.SendFlags |= 2;
-}
-
-bool conveyor_send(entity this, entity to, int sf)
+bool conveyor_send(entity this, entity to, int sendflags)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
- WriteByte(MSG_ENTITY, sf);
+ WriteByte(MSG_ENTITY, sendflags);
- if(sf & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
WriteByte(MSG_ENTITY, this.warpzone_isboxy);
WriteVector(MSG_ENTITY, this.origin);
WriteVector(MSG_ENTITY, this.movedir);
WriteByte(MSG_ENTITY, this.speed);
- WriteByte(MSG_ENTITY, this.state);
+ WriteByte(MSG_ENTITY, this.active);
WriteString(MSG_ENTITY, this.targetname);
WriteString(MSG_ENTITY, this.target);
}
- if(sf & 2)
- WriteByte(MSG_ENTITY, this.state);
+ if(sendflags & SF_TRIGGER_UPDATE)
+ WriteByte(MSG_ENTITY, this.active);
return true;
}
this.movedir *= this.speed;
setthink(this, conveyor_think);
this.nextthink = time;
+ this.setactive = generic_netlinked_setactive;
IFTARGETED
{
- this.use = conveyor_use;
- this.reset = conveyor_reset;
- this.reset(this);
+ // backwards compatibility
+ this.use = generic_netlinked_legacy_use;
}
- else
- this.state = 1;
+ this.reset = generic_netlinked_reset;
+ this.reset(this);
FixSize(this);
Net_LinkEntity(this, 0, false, conveyor_send);
- this.SendFlags |= 1;
+ this.SendFlags |= SF_TRIGGER_INIT;
}
spawnfunc(trigger_conveyor)
NET_HANDLE(ENT_CLIENT_CONVEYOR, bool isnew)
{
- int sf = ReadByte();
+ int sendflags = ReadByte();
- if(sf & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
this.warpzone_isboxy = ReadByte();
this.origin = ReadVector();
this.movedir = ReadVector();
this.speed = ReadByte();
- this.state = ReadByte();
+ this.active = ReadByte();
this.targetname = strzone(ReadString());
this.target = strzone(ReadString());
conveyor_init(this, isnew);
}
- if(sf & 2)
- this.state = ReadByte();
+ if(sendflags & SF_TRIGGER_UPDATE)
+ this.active = ReadByte();
return true;
}
#pragma once
+#include "../defs.qh"
IntrusiveList g_conveyed;
STATIC_INIT(g_conveyed) { g_conveyed = IL_NEW(); }
#include "door.qh"
+#include "door_rotating.qh"
/*
Doors are similar to buttons, but can spawn a fat trigger field around them
void door_go_down(entity this);
void door_go_up(entity this, entity actor, entity trigger);
-void door_rotating_go_down(entity this);
-void door_rotating_go_up(entity this, entity oth);
void door_blocked(entity this, entity blocker)
{
- if((this.spawnflags & 8)
+ if((this.spawnflags & DOOR_CRUSH)
#ifdef SVQC
&& (blocker.takedamage != DAMAGE_NO)
#elif defined(CSQC)
if (this.wait >= 0)
{
if (this.state == STATE_DOWN)
- if (this.classname == "door")
- {
- door_go_up (this, NULL, NULL);
- } else
- {
- door_rotating_go_up(this, blocker);
- }
+ {
+ if (this.classname == "door")
+ door_go_up(this, NULL, NULL);
+ else
+ door_rotating_go_up(this, blocker);
+ }
else
- if (this.classname == "door")
- {
- door_go_down (this);
- } else
- {
- door_rotating_go_down (this);
- }
+ {
+ if (this.classname == "door")
+ door_go_down(this);
+ else
+ door_rotating_go_down(this);
+ }
}
}
#ifdef SVQC
if(!door.itemkeys)
{
#ifdef SVQC
- play2(player, SND(TALK));
+ play2(player, door.noise);
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_DOOR_UNLOCKED);
#endif
return true;
door_go_up(e, actor, trigger);
} else {
// if the BIDIR spawnflag (==2) is set and the trigger has set trigger_reverse, reverse the opening direction
- if ((e.spawnflags & 2) && trigger.trigger_reverse!=0 && e.lip != 666 && e.state == STATE_BOTTOM) {
+ if ((e.spawnflags & DOOR_ROTATING_BIDIR) && trigger.trigger_reverse!=0 && e.lip != 666 && e.state == STATE_BOTTOM) {
e.lip = 666; // e.lip is used to remember reverse opening direction for door_rotating
e.pos2 = '0 0 0' - e.pos2;
}
// if BIDIR_IN_DOWN (==8) is set, prevent the door from reoping during closing if it is triggered from the wrong side
- if (!((e.spawnflags & 2) && (e.spawnflags & 8) && e.state == STATE_DOWN
+ if (!((e.spawnflags & DOOR_ROTATING_BIDIR) && (e.spawnflags & DOOR_ROTATING_BIDIR_IN_DOWN) && e.state == STATE_DOWN
&& (((e.lip == 666) && (trigger.trigger_reverse == 0)) || ((e.lip != 666) && (trigger.trigger_reverse != 0)))))
{
door_rotating_go_up(e, trigger);
void door_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
- if(this.spawnflags & DOOR_NOSPLASH)
+ if(this.spawnflags & NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
this.health = this.health - damage;
void door_generic_plat_blocked(entity this, entity blocker)
{
- if((this.spawnflags & 8) && (blocker.takedamage != DAMAGE_NO)) { // Kill Kill Kill!!
+ if((this.spawnflags & DOOR_CRUSH) && (blocker.takedamage != DAMAGE_NO)) { // Kill Kill Kill!!
#ifdef SVQC
Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, blocker.origin, '0 0 0');
#endif
}
}
-void door_rotating_hit_top(entity this)
-{
- if (this.noise1 != "")
- _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
- this.state = STATE_TOP;
- if (this.spawnflags & DOOR_TOGGLE)
- return; // don't come down automatically
- setthink(this, door_rotating_go_down);
- this.nextthink = this.ltime + this.wait;
-}
-
-void door_rotating_hit_bottom(entity this)
-{
- if (this.noise1 != "")
- _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
- if (this.lip==666) // this.lip is used to remember reverse opening direction for door_rotating
- {
- this.pos2 = '0 0 0' - this.pos2;
- this.lip = 0;
- }
- this.state = STATE_BOTTOM;
-}
-
-void door_rotating_go_down(entity this)
-{
- if (this.noise2 != "")
- _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
- if (this.max_health)
- {
- this.takedamage = DAMAGE_YES;
- this.health = this.max_health;
- }
-
- this.state = STATE_DOWN;
- SUB_CalcAngleMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_rotating_hit_bottom);
-}
-
-void door_rotating_go_up(entity this, entity oth)
-{
- if (this.state == STATE_UP)
- return; // already going up
-
- if (this.state == STATE_TOP)
- { // reset top wait time
- this.nextthink = this.ltime + this.wait;
- return;
- }
- if (this.noise2 != "")
- _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
- this.state = STATE_UP;
- SUB_CalcAngleMove (this, this.pos2, TSPEED_LINEAR, this.speed, door_rotating_hit_top);
-
- string oldmessage;
- oldmessage = this.message;
- this.message = "";
- SUB_UseTargets(this, NULL, oth); // TODO: is oth needed here?
- this.message = oldmessage;
-}
-
-
/*
=========================================
door trigger
entity LinkDoors_nextent(entity cur, entity near, entity pass)
{
- while((cur = find(cur, classname, pass.classname)) && ((cur.spawnflags & 4) || cur.enemy))
+ while((cur = find(cur, classname, pass.classname)) && ((cur.spawnflags & DOOR_DONT_LINK) || cur.enemy))
{
}
return cur;
if (this.enemy)
return; // already linked by another door
- if (this.spawnflags & 4)
+ if (this.spawnflags & DOOR_DONT_LINK)
{
this.owner = this.enemy = this;
#ifdef SVQC
-// spawnflags require key (for now only func_door)
-spawnfunc(func_door)
+// common code for func_door and func_door_rotating spawnfuncs
+void door_init_shared(entity this)
{
- // Quake 1 keys compatibility
- if (this.spawnflags & SPAWNFLAGS_GOLD_KEY)
- this.itemkeys |= ITEM_KEY_BIT(0);
- if (this.spawnflags & SPAWNFLAGS_SILVER_KEY)
- this.itemkeys |= ITEM_KEY_BIT(1);
-
- SetMovedir(this);
-
this.max_health = this.health;
- if (!InitMovingBrushTrigger(this))
- return;
- this.effects |= EF_LOWPRECISION;
- this.classname = "door";
+ // unlock sound
if(this.noise == "")
+ {
this.noise = "misc/talk.wav";
+ }
+ // door still locked sound
if(this.noise3 == "")
+ {
this.noise3 = "misc/talk.wav";
+ }
precache_sound(this.noise);
precache_sound(this.noise3);
- setblocked(this, door_blocked);
- this.use = door_use;
-
- if(this.dmg && (this.message == ""))
+ if((this.dmg || (this.spawnflags & DOOR_CRUSH)) && (this.message == ""))
+ {
this.message = "was squished";
- if(this.dmg && (this.message2 == ""))
+ }
+ if((this.dmg || (this.spawnflags & DOOR_CRUSH)) && (this.message2 == ""))
+ {
this.message2 = "was squished by";
+ }
+ // TODO: other soundpacks
if (this.sounds > 0)
{
this.noise2 = "plats/medplat1.wav";
this.noise1 = "plats/medplat2.wav";
}
- if(this.noise1 && this.noise1 != "") { precache_sound(this.noise1); }
- if(this.noise2 && this.noise2 != "") { precache_sound(this.noise2); }
+ // sound when door stops moving
+ if(this.noise1 && this.noise1 != "")
+ {
+ precache_sound(this.noise1);
+ }
+ // sound when door is moving
+ if(this.noise2 && this.noise2 != "")
+ {
+ precache_sound(this.noise2);
+ }
- if (!this.speed)
- this.speed = 100;
if (!this.wait)
+ {
this.wait = 3;
+ }
if (!this.lip)
+ {
this.lip = 8;
+ }
+
+ this.state = STATE_BOTTOM;
+
+ if (this.health)
+ {
+ //this.canteamdamage = true; // TODO
+ this.takedamage = DAMAGE_YES;
+ this.event_damage = door_damage;
+ }
+
+ if (this.items)
+ {
+ this.wait = -1;
+ }
+}
+
+// spawnflags require key (for now only func_door)
+spawnfunc(func_door)
+{
+ // Quake 1 keys compatibility
+ if (this.spawnflags & SPAWNFLAGS_GOLD_KEY)
+ this.itemkeys |= ITEM_KEY_BIT(0);
+ if (this.spawnflags & SPAWNFLAGS_SILVER_KEY)
+ this.itemkeys |= ITEM_KEY_BIT(1);
+
+ SetMovedir(this);
+
+ if (!InitMovingBrushTrigger(this))
+ return;
+ this.effects |= EF_LOWPRECISION;
+ this.classname = "door";
+
+ setblocked(this, door_blocked);
+ this.use = door_use;
this.pos1 = this.origin;
this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
if (this.spawnflags & DOOR_START_OPEN)
InitializeEntity(this, door_init_startopen, INITPRIO_SETLOCATION);
- this.state = STATE_BOTTOM;
+ door_init_shared(this);
- if (this.health)
+ if (!this.speed)
{
- //this.canteamdamage = true; // TODO
- this.takedamage = DAMAGE_YES;
- this.event_damage = door_damage;
+ this.speed = 100;
}
- if (this.items)
- this.wait = -1;
-
settouch(this, door_touch);
// LinkDoors can't be done until all of the doors have been spawned, so
#pragma once
-// door constants
-const int DOOR_START_OPEN = 1;
-const int DOOR_DONT_LINK = 4;
-const int DOOR_TOGGLE = 32;
-const int DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
+const int DOOR_START_OPEN = BIT(0);
+const int DOOR_DONT_LINK = BIT(2);
+const int SPAWNFLAGS_GOLD_KEY = BIT(3); // Quake 1 compat, can only be used with func_door!
+const int SPAWNFLAGS_SILVER_KEY = BIT(4); // Quake 1 compat, can only be used with func_door!
+const int DOOR_TOGGLE = BIT(5);
-const int DOOR_NONSOLID = 1024;
+const int DOOR_NONSOLID = BIT(10);
+const int DOOR_CRUSH = BIT(11); // can't use CRUSH cause that is the same as DOOR_DONT_LINK
-const int SPAWNFLAGS_GOLD_KEY = 8;
-const int SPAWNFLAGS_SILVER_KEY = 16;
#ifdef CSQC
// stuff for preload
#include "door_rotating.qh"
-#ifdef SVQC
/*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
if two doors touch, they are assumed to be connected and operate as a unit.
FIXME: only one sound set available at the time being
*/
+#ifdef GAMEQC
+void door_rotating_hit_top(entity this)
+{
+ if (this.noise1 != "")
+ _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+ this.state = STATE_TOP;
+ if (this.spawnflags & DOOR_TOGGLE)
+ return; // don't come down automatically
+ setthink(this, door_rotating_go_down);
+ this.nextthink = this.ltime + this.wait;
+}
+
+void door_rotating_hit_bottom(entity this)
+{
+ if (this.noise1 != "")
+ _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+ if (this.lip==666) // this.lip is used to remember reverse opening direction for door_rotating
+ {
+ this.pos2 = '0 0 0' - this.pos2;
+ this.lip = 0;
+ }
+ this.state = STATE_BOTTOM;
+}
+
+void door_rotating_go_down(entity this)
+{
+ if (this.noise2 != "")
+ _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
+ if (this.max_health)
+ {
+ this.takedamage = DAMAGE_YES;
+ this.health = this.max_health;
+ }
+
+ this.state = STATE_DOWN;
+ SUB_CalcAngleMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_rotating_hit_bottom);
+}
+
+void door_rotating_go_up(entity this, entity oth)
+{
+ if (this.state == STATE_UP)
+ return; // already going up
+
+ if (this.state == STATE_TOP)
+ { // reset top wait time
+ this.nextthink = this.ltime + this.wait;
+ return;
+ }
+ if (this.noise2 != "")
+ _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
+ this.state = STATE_UP;
+ SUB_CalcAngleMove (this, this.pos2, TSPEED_LINEAR, this.speed, door_rotating_hit_top);
+
+ string oldmessage;
+ oldmessage = this.message;
+ this.message = "";
+ SUB_UseTargets(this, NULL, oth); // TODO: is oth needed here?
+ this.message = oldmessage;
+}
+#endif
+
+#ifdef SVQC
void door_rotating_reset(entity this)
{
this.angles = this.pos1;
this.pos1 = this.movedir;
}
-
spawnfunc(func_door_rotating)
{
-
//if (!this.deathtype) // map makers can override this
// this.deathtype = " got in the way";
// I abuse "movedir" for denoting the axis for now
- if (this.spawnflags & 64) // X (untested)
+ if (this.spawnflags & DOOR_ROTATING_XAXIS)
this.movedir = '0 0 1';
- else if (this.spawnflags & 128) // Y (untested)
+ else if (this.spawnflags & DOOR_ROTATING_YAXIS)
this.movedir = '1 0 0';
else // Z
this.movedir = '0 1 0';
this.movedir = this.movedir * this.angles_y;
this.angles = '0 0 0';
- this.max_health = this.health;
this.avelocity = this.movedir;
if (!InitMovingBrushTrigger(this))
return;
setblocked(this, door_blocked);
this.use = door_use;
- if(this.spawnflags & 8)
- this.dmg = 10000;
-
- if(this.dmg && (this.message == ""))
- this.message = "was squished";
- if(this.dmg && (this.message2 == ""))
- this.message2 = "was squished by";
-
- if (this.sounds > 0)
- {
- precache_sound ("plats/medplat1.wav");
- precache_sound ("plats/medplat2.wav");
- this.noise2 = "plats/medplat1.wav";
- this.noise1 = "plats/medplat2.wav";
- }
-
- if (!this.speed)
- this.speed = 50;
- if (!this.wait)
- this.wait = 1;
- this.lip = 0; // this.lip is used to remember reverse opening direction for door_rotating
-
this.pos1 = '0 0 0';
this.pos2 = this.movedir;
if (this.spawnflags & DOOR_START_OPEN)
InitializeEntity(this, door_rotating_init_startopen, INITPRIO_SETLOCATION);
- this.state = STATE_BOTTOM;
-
- if (this.health)
+ door_init_shared(this);
+ if (!this.speed)
{
- //this.canteamdamage = true; // TODO
- this.takedamage = DAMAGE_YES;
- this.event_damage = door_damage;
+ this.speed = 50;
}
-
- if (this.items)
- this.wait = -1;
+ this.lip = 0; // this.lip is used to remember reverse opening direction for door_rotating
settouch(this, door_touch);
#pragma once
+
+
+const int DOOR_ROTATING_BIDIR = BIT(1);
+const int DOOR_ROTATING_BIDIR_IN_DOWN = BIT(3);
+
+const int DOOR_ROTATING_XAXIS = BIT(6);
+const int DOOR_ROTATING_YAXIS = BIT(7);
+
+
+#ifdef GAMEQC
+void door_rotating_go_down(entity this);
+void door_rotating_go_up(entity this, entity oth);
+#endif
void fd_secret_move6(entity this);
void fd_secret_done(entity this);
-const float SECRET_OPEN_ONCE = 1; // stays open
-const float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
-const float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
-const float SECRET_NO_SHOOT = 8; // only opened by trigger
-const float SECRET_YES_SHOOT = 16; // shootable even if targeted
-
void fd_secret_use(entity this, entity actor, entity trigger)
{
float temp;
_sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
this.nextthink = this.ltime + 0.1;
- temp = 1 - (this.spawnflags & SECRET_1ST_LEFT); // 1 or -1
+ temp = 1 - (this.spawnflags & DOOR_SECRET_1ST_LEFT); // 1 or -1
makevectors(this.mangle);
if (!this.t_width)
{
- if (this.spawnflags & SECRET_1ST_DOWN)
+ if (this.spawnflags & DOOR_SECRET_1ST_DOWN)
this.t_width = fabs(v_up * this.size);
else
this.t_width = fabs(v_right * this.size);
if (!this.t_length)
this.t_length = fabs(v_forward * this.size);
- if (this.spawnflags & SECRET_1ST_DOWN)
+ if (this.spawnflags & DOOR_SECRET_1ST_DOWN)
this.dest1 = this.origin - v_up * this.t_width;
else
this.dest1 = this.origin + v_right * (this.t_width * temp);
{
if (this.noise3 != "")
_sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
- if (!(this.spawnflags & SECRET_OPEN_ONCE))
+ if (!(this.spawnflags & DOOR_SECRET_OPEN_ONCE) && this.wait >= 0)
{
this.nextthink = this.ltime + this.wait;
setthink(this, fd_secret_move4);
void fd_secret_done(entity this)
{
- if (this.spawnflags&SECRET_YES_SHOOT)
+ if (this.spawnflags&DOOR_SECRET_YES_SHOOT)
{
this.health = 10000;
this.takedamage = DAMAGE_YES;
void secret_reset(entity this)
{
- if (this.spawnflags & SECRET_YES_SHOOT)
+ if (this.spawnflags & DOOR_SECRET_YES_SHOOT)
{
this.health = 10000;
this.takedamage = DAMAGE_YES;
/*if (!this.deathtype) // map makers can override this
this.deathtype = " got in the way";*/
- if (!this.dmg) this.dmg = 2;
+ if (!this.dmg)
+ {
+ this.dmg = 2;
+ }
// Magic formula...
this.mangle = this.angles;
if (!InitMovingBrushTrigger(this)) return;
this.effects |= EF_LOWPRECISION;
- if (this.noise == "") this.noise = "misc/talk.wav";
+ // TODO: other soundpacks
+ if (this.sounds > 0)
+ {
+ this.noise1 = "plats/medplat1.wav";
+ this.noise2 = "plats/medplat1.wav";
+ this.noise3 = "plats/medplat2.wav";
+ }
+
+ // sound on touch
+ if (this.noise == "")
+ {
+ this.noise = "misc/talk.wav";
+ }
precache_sound(this.noise);
+ // sound while moving backwards
+ if (this.noise1 && this.noise1 != "")
+ {
+ precache_sound(this.noise1);
+ }
+ // sound while moving sideways
+ if (this.noise2 && this.noise2 != "")
+ {
+ precache_sound(this.noise2);
+ }
+ // sound when door stops moving
+ if (this.noise3 && this.noise3 != "")
+ {
+ precache_sound(this.noise3);
+ }
settouch(this, secret_touch);
setblocked(this, secret_blocked);
{
}
else
- this.spawnflags |= SECRET_YES_SHOOT;
+ this.spawnflags |= DOOR_SECRET_YES_SHOOT;
- if (this.spawnflags & SECRET_YES_SHOOT)
+ if (this.spawnflags & DOOR_SECRET_YES_SHOOT)
{
//this.canteamdamage = true; // TODO
this.health = 10000;
#pragma once
+
+
+const int DOOR_SECRET_OPEN_ONCE = BIT(0); // stays open - LEGACY, set wait to -1 instead
+const int DOOR_SECRET_1ST_LEFT = BIT(1); // 1st move is left of arrow
+const int DOOR_SECRET_1ST_DOWN = BIT(2); // 1st move is down from arrow
+const int DOOR_SECRET_NO_SHOOT = BIT(3); // only opened by trigger
+const int DOOR_SECRET_YES_SHOOT = BIT(4); // shootable even if targeted
void func_ladder_remove(entity this)
{
- if(this.classname) { strunzone(this.classname); }
- this.classname = string_null;
+ strfree(this.classname);
}
NET_HANDLE(ENT_CLIENT_LADDER, bool isnew)
spawnfunc(func_plat)
{
- if (this.sounds == 0) this.sounds = 2;
-
- if (this.spawnflags & 4) this.dmg = 10000;
+ if (this.spawnflags & CRUSH)
+ {
+ this.dmg = 10000;
+ }
- if (this.dmg && (this.message == "")) this.message = "was squished";
- if (this.dmg && (this.message2 == "")) this.message2 = "was squished by";
+ if (this.dmg && (this.message == ""))
+ {
+ this.message = "was squished";
+ }
+ if (this.dmg && (this.message2 == ""))
+ {
+ this.message2 = "was squished by";
+ }
if (this.sounds == 1)
{
this.noise1 = "plats/medplat2.wav";
}
+ // WARNING: backwards compatibility because people don't use already existing fields :(
if (this.sound1)
this.noise = this.sound1;
if (this.sound2)
this.noise1 = this.sound2;
- if(this.noise && this.noise != "") { precache_sound(this.noise); }
- if(this.noise1 && this.noise1 != "") { precache_sound(this.noise1); }
+ if(this.noise && this.noise != "")
+ {
+ precache_sound(this.noise);
+ }
+ if(this.noise1 && this.noise1 != "")
+ {
+ precache_sound(this.noise1);
+ }
this.mangle = this.angles;
this.angles = '0 0 0';
#ifdef SVQC
// NOTE: also contains func_sparks
-bool pointparticles_SendEntity(entity this, entity to, float fl)
+bool pointparticles_SendEntity(entity this, entity to, float sendflags)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
// optional features to save space
- fl = fl & 0x0F;
- if(this.spawnflags & 2)
- fl |= 0x10; // absolute count on toggle-on
+ sendflags = sendflags & 0x0F;
+ if(this.spawnflags & PARTICLES_IMPULSE)
+ sendflags |= SF_POINTPARTICLES_IMPULSE; // absolute count on toggle-on
if(this.movedir != '0 0 0' || this.velocity != '0 0 0')
- fl |= 0x20; // 4 bytes - saves CPU
+ sendflags |= SF_POINTPARTICLES_MOVING; // 4 bytes - saves CPU
if(this.waterlevel || this.count != 1)
- fl |= 0x40; // 4 bytes - obscure features almost never used
+ sendflags |= SF_POINTPARTICLES_JITTER_AND_COUNT; // 4 bytes - obscure features almost never used
if(this.mins != '0 0 0' || this.maxs != '0 0 0')
- fl |= 0x80; // 14 bytes - saves lots of space
+ sendflags |= SF_POINTPARTICLES_BOUNDS; // 14 bytes - saves lots of space
- WriteByte(MSG_ENTITY, fl);
- if(fl & 2)
+ WriteByte(MSG_ENTITY, sendflags);
+ if(sendflags & SF_TRIGGER_UPDATE)
{
- if(this.state)
+ if(this.active == ACTIVE_ACTIVE)
WriteCoord(MSG_ENTITY, this.impulse);
else
WriteCoord(MSG_ENTITY, 0); // off
}
- if(fl & 4)
+ if(sendflags & SF_TRIGGER_RESET)
{
WriteVector(MSG_ENTITY, this.origin);
}
- if(fl & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
if(this.model != "null")
{
WriteShort(MSG_ENTITY, this.modelindex);
- if(fl & 0x80)
+ if(sendflags & SF_POINTPARTICLES_BOUNDS)
{
WriteVector(MSG_ENTITY, this.mins);
WriteVector(MSG_ENTITY, this.maxs);
else
{
WriteShort(MSG_ENTITY, 0);
- if(fl & 0x80)
+ if(sendflags & SF_POINTPARTICLES_BOUNDS)
{
WriteVector(MSG_ENTITY, this.maxs);
}
}
WriteShort(MSG_ENTITY, this.cnt);
WriteString(MSG_ENTITY, this.mdl);
- if(fl & 0x20)
+ if(sendflags & SF_POINTPARTICLES_MOVING)
{
WriteShort(MSG_ENTITY, compressShortVector(this.velocity));
WriteShort(MSG_ENTITY, compressShortVector(this.movedir));
}
- if(fl & 0x40)
+ if(sendflags & SF_POINTPARTICLES_JITTER_AND_COUNT)
{
WriteShort(MSG_ENTITY, this.waterlevel * 16.0);
WriteByte(MSG_ENTITY, this.count * 16.0);
return 1;
}
-void pointparticles_use(entity this, entity actor, entity trigger)
-{
- this.state = !this.state;
- this.SendFlags |= 2;
-}
-
void pointparticles_think(entity this)
{
if(this.origin != this.oldorigin)
{
- this.SendFlags |= 4;
+ this.SendFlags |= SF_TRIGGER_RESET;
this.oldorigin = this.origin;
}
this.nextthink = time;
}
-void pointparticles_reset(entity this)
-{
- if(this.spawnflags & 1)
- this.state = 1;
- else
- this.state = 0;
-}
-
spawnfunc(func_pointparticles)
{
if(this.model != "") { precache_model(this.model); _setmodel(this, this.model); }
setsize(this, '0 0 0', this.maxs - this.mins);
}
//if(!this.cnt) this.cnt = _particleeffectnum(this.mdl);
+ this.setactive = generic_netlinked_setactive;
- Net_LinkEntity(this, (this.spawnflags & 4), 0, pointparticles_SendEntity);
+ Net_LinkEntity(this, (this.spawnflags & PARTICLES_VISCULLING), 0, pointparticles_SendEntity);
IFTARGETED
{
- this.use = pointparticles_use;
- this.reset = pointparticles_reset;
- this.reset(this);
+ // backwards compatibility
+ this.use = generic_netlinked_legacy_use;
}
- else
- this.state = 1;
+ this.reset = generic_netlinked_reset;
+ this.reset(this);
setthink(this, pointparticles_think);
this.nextthink = time;
}
spawnfunc(func_sparks)
{
- // this.cnt is the amount of sparks that one burst will spawn
- if(this.cnt < 1) {
- this.cnt = 25.0; // nice default value
+ if(this.count < 1) {
+ this.count = 25.0; // nice default value
}
- // this.wait is the probability that a sparkthink will spawn a spark shower
- // range: 0 - 1, but 0 makes little sense, so...
- if(this.wait < 0.05) {
- this.wait = 0.25; // nice default value
+ if(this.impulse < 0.5) {
+ this.impulse = 2.5; // nice default value
}
- this.count = this.cnt;
this.mins = '0 0 0';
this.maxs = '0 0 0';
this.velocity = '0 0 -1';
this.mdl = "TE_SPARK";
- this.impulse = 10 * this.wait; // by default 2.5/sec
- this.wait = 0;
this.cnt = 0; // use mdl
spawnfunc_func_pointparticles(this);
.int dphitcontentsmask;
entityclass(PointParticles);
-class(PointParticles) .int cnt; // effect number
-class(PointParticles) .vector velocity; // particle velocity
-class(PointParticles) .float waterlevel; // direction jitter
-class(PointParticles) .int count; // count multiplier
-class(PointParticles) .int impulse; // density
-class(PointParticles) .string noise; // sound
-class(PointParticles) .float atten;
-class(PointParticles) .float volume;
-class(PointParticles) .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
-class(PointParticles) .vector movedir; // trace direction
-class(PointParticles) .float glow_color; // palette index
+classfield(PointParticles) .int cnt; // effect number
+classfield(PointParticles) .vector velocity; // particle velocity
+classfield(PointParticles) .float waterlevel; // direction jitter
+classfield(PointParticles) .int count; // count multiplier
+classfield(PointParticles) .int impulse; // density
+classfield(PointParticles) .string noise; // sound
+classfield(PointParticles) .float atten;
+classfield(PointParticles) .float volume;
+classfield(PointParticles) .float absolute; // 1 = count per second is absolute, ABSOLUTE_ONLY_SPAWN_AT_TOGGLE = only spawn at toggle
+classfield(PointParticles) .vector movedir; // trace direction
+classfield(PointParticles) .float glow_color; // palette index
+
+const int ABSOLUTE_ONLY_SPAWN_AT_TOGGLE = 2;
void Draw_PointParticles(entity this)
{
o = this.origin;
sz = this.maxs - this.mins;
n = doBGMScript(this);
- if(this.absolute == 2)
+ if(this.absolute == ABSOLUTE_ONLY_SPAWN_AT_TOGGLE)
{
if(n >= 0)
n = this.just_toggled ? this.impulse : 0;
void Ent_PointParticles_Remove(entity this)
{
- if(this.noise)
- strunzone(this.noise);
- this.noise = string_null;
- if(this.bgmscript)
- strunzone(this.bgmscript);
- this.bgmscript = string_null;
- if(this.mdl)
- strunzone(this.mdl);
- this.mdl = string_null;
+ strfree(this.noise);
+ strfree(this.bgmscript);
+ strfree(this.mdl);
}
NET_HANDLE(ENT_CLIENT_POINTPARTICLES, bool isnew)
{
float i;
vector v;
- int f = ReadByte();
- if(f & 2)
+ int sendflags = ReadByte();
+ if(sendflags & SF_TRIGGER_UPDATE)
{
i = ReadCoord(); // density (<0: point, >0: volume)
if(i && !this.impulse && (this.cnt || this.mdl)) // this.cnt check is so it only happens if the ent already existed
this.just_toggled = 1;
this.impulse = i;
}
- if(f & 4)
+ if(sendflags & SF_TRIGGER_RESET)
{
this.origin = ReadVector();
}
- if(f & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
this.modelindex = ReadShort();
- if(f & 0x80)
+ if(sendflags & SF_POINTPARTICLES_BOUNDS)
{
if(this.modelindex)
{
this.cnt = ReadShort(); // effect number
this.mdl = strzone(ReadString()); // effect string
- if(f & 0x20)
+ if(sendflags & SF_POINTPARTICLES_MOVING)
{
this.velocity = decompressShortVector(ReadShort());
this.movedir = decompressShortVector(ReadShort());
{
this.velocity = this.movedir = '0 0 0';
}
- if(f & 0x40)
+ if(sendflags & SF_POINTPARTICLES_JITTER_AND_COUNT)
{
this.waterlevel = ReadShort() / 16.0;
this.count = ReadByte() / 16.0;
this.waterlevel = 0;
this.count = 1;
}
- if(this.noise)
- strunzone(this.noise);
- if(this.bgmscript)
- strunzone(this.bgmscript);
- this.noise = strzone(ReadString());
+ strcpy(this.noise, ReadString());
if(this.noise != "")
{
this.atten = ReadByte() / 64.0;
this.volume = ReadByte() / 255.0;
}
- this.bgmscript = strzone(ReadString());
+ strcpy(this.bgmscript, ReadString());
if(this.bgmscript != "")
{
this.bgmscriptattack = ReadByte() / 64.0;
return = true;
- if(f & 2)
+ if(sendflags & SF_TRIGGER_UPDATE)
{
this.absolute = (this.impulse >= 0);
if(!this.absolute)
{
v = this.maxs - this.mins;
- this.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
+ this.impulse *= -v.x * v.y * v.z / (64**3); // relative: particles per 64^3 cube
}
}
- if(f & 0x10)
- this.absolute = 2;
+ if(sendflags & SF_POINTPARTICLES_IMPULSE)
+ this.absolute = ABSOLUTE_ONLY_SPAWN_AT_TOGGLE;
setorigin(this, this.origin);
setsize(this, this.mins, this.maxs);
#pragma once
+
+// spawnflags
+const int PARTICLES_IMPULSE = BIT(1);
+const int PARTICLES_VISCULLING = BIT(2);
+
+// sendflags
+const int SF_POINTPARTICLES_IMPULSE = BIT(4);
+const int SF_POINTPARTICLES_MOVING = BIT(5); // Send velocity and movedir
+const int SF_POINTPARTICLES_JITTER_AND_COUNT = BIT(6); // Send waterlevel (=jitter) and count
+const int SF_POINTPARTICLES_BOUNDS = BIT(7); // Send min and max of the brush
this.solid = SOLID_NOT;
SetBrushEntityModel(this);
if (!this.cnt)
+ {
this.cnt = 12;
+ }
if (!this.count)
this.count = 2000;
- this.count = 0.01 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
+ // relative to absolute particle count
+ this.count = this.count * (this.size_x / 1024) * (this.size_y / 1024);
if (this.count < 1)
this.count = 1;
if(this.count > 65535)
this.count = 65535;
- this.state = 1; // 1 is rain, 0 is snow
- this.Version = 1;
+ this.state = RAINSNOW_RAIN;
Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
}
this.solid = SOLID_NOT;
SetBrushEntityModel(this);
if (!this.cnt)
+ {
this.cnt = 12;
+ }
if (!this.count)
this.count = 2000;
- this.count = 0.01 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
+ // relative to absolute particle count
+ this.count = this.count * (this.size_x / 1024) * (this.size_y / 1024);
if (this.count < 1)
this.count = 1;
if(this.count > 65535)
this.count = 65535;
- this.state = 0; // 1 is rain, 0 is snow
- this.Version = 1;
+ this.state = RAINSNOW_SNOW;
Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
}
NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew)
{
- this.impulse = ReadByte(); // Rain, Snow, or Whatever
+ this.state = ReadByte(); // Rain, Snow, or Whatever
this.origin = ReadVector();
this.maxs = ReadVector();
this.velocity = decompressShortVector(ReadShort());
- this.count = ReadShort() * 10;
+ this.count = ReadShort();
this.glow_color = ReadByte(); // color
return = true;
setsize(this, this.mins, this.maxs);
this.solid = SOLID_NOT;
if (isnew) IL_PUSH(g_drawables, this);
- if(this.impulse)
+ if(this.state == RAINSNOW_RAIN)
this.draw = Draw_Rain;
else
this.draw = Draw_Snow;
#pragma once
+
+
+const int RAINSNOW_SNOW = 0;
+const int RAINSNOW_RAIN = 1;
#include "rotating.qh"
#ifdef SVQC
-const int FUNC_ROTATING_STARTOFF = BIT(4);
void func_rotating_setactive(entity this, int astate)
{
this.active = astate;
if(this.active == ACTIVE_NOT)
+ {
this.avelocity = '0 0 0';
+ stopsound(this, CH_AMBIENT_SINGLE);
+ }
else
+ {
this.avelocity = this.pos1;
+ if(this.noise && this.noise != "")
+ {
+ _sound(this, CH_AMBIENT_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+ }
+ }
}
void func_rotating_reset(entity this)
if(this.spawnflags & FUNC_ROTATING_STARTOFF)
{
- this.avelocity = '0 0 0';
- this.active = ACTIVE_NOT;
+ this.setactive(this, ACTIVE_NOT);
}
else
{
- this.avelocity = this.pos1;
- this.active = ACTIVE_ACTIVE;
+ this.setactive(this, ACTIVE_ACTIVE);
+ }
+}
+
+void func_rotating_init_for_player(entity this, entity player)
+{
+ if (this.noise && this.noise != "" && this.active == ACTIVE_ACTIVE && IS_REAL_CLIENT(player))
+ {
+ msg_entity = player;
+ soundto (MSG_ONE, this, CH_AMBIENT_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
}
}
spawnfunc(func_rotating)
{
- if (this.noise != "")
+ if (this.noise && this.noise != "")
{
precache_sound(this.noise);
- ambientsound(this.origin, this.noise, VOL_BASE, ATTEN_IDLE);
}
this.setactive = func_rotating_setactive;
if (!this.speed)
this.speed = 100;
- // FIXME: test if this turns the right way, then remove this comment (negate as needed)
- if (this.spawnflags & BIT(2)) // X (untested)
+ if (this.spawnflags & FUNC_ROTATING_XAXIS)
this.avelocity = '0 0 1' * this.speed;
- // FIXME: test if this turns the right way, then remove this comment (negate as needed)
- else if (this.spawnflags & BIT(3)) // Y (untested)
+ else if (this.spawnflags & FUNC_ROTATING_YAXIS)
this.avelocity = '1 0 0' * this.speed;
- // FIXME: test if this turns the right way, then remove this comment (negate as needed)
else // Z
this.avelocity = '0 1 0' * this.speed;
this.pos1 = this.avelocity;
- // do this after setting pos1, so we can safely reactivate the func_rotating
- if(this.spawnflags & FUNC_ROTATING_STARTOFF)
- {
- this.avelocity = '0 0 0';
- this.active = ACTIVE_NOT;
- }
- else
- this.active = ACTIVE_ACTIVE;
-
if(this.dmg && (this.message == ""))
this.message = " was squished";
if(this.dmg && (this.message2 == ""))
setthink(this, SUB_NullThink); // for PushMove
this.reset = func_rotating_reset;
+ this.reset(this);
+
+ // maybe send sound to new players
+ IL_PUSH(g_initforplayer, this);
+ this.init_for_player = func_rotating_init_for_player;
}
#endif
#pragma once
+
+
+const int FUNC_ROTATING_XAXIS = BIT(2);
+const int FUNC_ROTATING_YAXIS = BIT(3);
+const int FUNC_ROTATING_STARTOFF = BIT(4);
entity targ, cp;
vector ang;
targ = this.future_target;
- if((this.spawnflags & 1) && targ.curvetarget)
+ if((this.spawnflags & TRAIN_CURVE) && targ.curvetarget)
cp = find(NULL, targetname, targ.curvetarget);
else
cp = NULL;
#ifdef SVQC
entity tg = this.future_target;
- if(tg.spawnflags & 4)
+ if(tg.spawnflags & TRAIN_NEEDACTIVATION)
{
this.use = train_use;
setthink(this, func_null);
this.target_random = targ.target_random;
this.future_target = train_next_find(targ);
- if (this.spawnflags & 1)
+ if (this.spawnflags & TRAIN_CURVE)
{
if(targ.curvetarget)
{
{
this.nextthink = this.ltime + 1;
setthink(this, train_next);
- this.use = func_null; // not again
+ this.use = func_null; // not again, next target can set it again if needed
if(trigger.target2 && trigger.target2 != "")
this.future_target = find(NULL, targetname, trigger.target2);
}
objerror(this, "func_train_find: no next target");
setorigin(this, targ.origin - this.view_ofs);
- if(!(this.spawnflags & 4))
+ if(!(this.spawnflags & TRAIN_NEEDACTIVATION))
{
this.nextthink = this.ltime + 1;
setthink(this, train_next);
return;
this.effects |= EF_LOWPRECISION;
- if(this.spawnflags & 4)
+ if(this.spawnflags & TRAIN_NEEDACTIVATION)
this.use = train_use;
- if (this.spawnflags & 2)
+ if (this.spawnflags & TRAIN_TURN)
{
this.platmovetype_turn = true;
this.view_ofs = '0 0 0'; // don't offset a rotating train, origin works differently now
#pragma once
+
+const int TRAIN_CURVE = BIT(0);
+const int TRAIN_TURN = BIT(1);
+const int TRAIN_NEEDACTIVATION = BIT(2);
+
#ifdef CSQC
.float dmgtime;
#endif
.float targetfactor, target2factor, target3factor, target4factor;
.vector targetnormal, target2normal, target3normal, target4normal;
-vector func_vectormamamam_origin(entity o, float t)
+vector func_vectormamamam_origin(entity o, float timestep)
{
vector v, p;
- float f;
+ float flags;
entity e;
- f = o.spawnflags;
+ flags = o.spawnflags;
v = '0 0 0';
e = o.wp00;
if(e)
{
- p = e.origin + t * e.velocity;
- if(f & 1)
+ p = e.origin + timestep * e.velocity;
+ if(flags & PROJECT_ON_TARGETNORMAL)
v = v + (p * o.targetnormal) * o.targetnormal * o.targetfactor;
else
v = v + (p - (p * o.targetnormal) * o.targetnormal) * o.targetfactor;
e = o.wp01;
if(e)
{
- p = e.origin + t * e.velocity;
- if(f & 2)
+ p = e.origin + timestep * e.velocity;
+ if(flags & PROJECT_ON_TARGET2NORMAL)
v = v + (p * o.target2normal) * o.target2normal * o.target2factor;
else
v = v + (p - (p * o.target2normal) * o.target2normal) * o.target2factor;
e = o.wp02;
if(e)
{
- p = e.origin + t * e.velocity;
- if(f & 4)
+ p = e.origin + timestep * e.velocity;
+ if(flags & PROJECT_ON_TARGET3NORMAL)
v = v + (p * o.target3normal) * o.target3normal * o.target3factor;
else
v = v + (p - (p * o.target3normal) * o.target3normal) * o.target3factor;
e = o.wp03;
if(e)
{
- p = e.origin + t * e.velocity;
- if(f & 8)
+ p = e.origin + timestep * e.velocity;
+ if(flags & PROJECT_ON_TARGET4NORMAL)
v = v + (p * o.target4normal) * o.target4normal * o.target4factor;
else
v = v + (p - (p * o.target4normal) * o.target4normal) * o.target4factor;
void func_vectormamamam_controller_think(entity this)
{
- this.nextthink = time + 0.1;
+ this.nextthink = time + vectormamamam_timestep;
if(this.owner.active != ACTIVE_ACTIVE)
{
}
if(this.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
- this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, 0.1) - this.owner.origin) * 10;
+ this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, vectormamamam_timestep) - this.owner.origin) * 10;
}
void func_vectormamamam_findtarget(entity this)
setthink(controller, func_vectormamamam_controller_think);
}
+void func_vectormamamam_setactive(entity this, int astate)
+{
+ if (astate == ACTIVE_TOGGLE)
+ {
+ if(this.active == ACTIVE_ACTIVE)
+ this.active = ACTIVE_NOT;
+ else
+ this.active = ACTIVE_ACTIVE;
+ }
+ else
+ this.active = astate;
+
+ if(this.active == ACTIVE_NOT)
+ {
+ stopsound(this, CH_TRIGGER_SINGLE);
+ }
+ else
+ {
+ if(this.noise && this.noise != "")
+ {
+ _sound(this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+ }
+ }
+}
+
+void func_vectormamamam_init_for_player(entity this, entity player)
+{
+ if (this.noise && this.noise != "" && this.active == ACTIVE_ACTIVE && IS_REAL_CLIENT(player))
+ {
+ msg_entity = player;
+ soundto(MSG_ONE, this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+ }
+}
+
spawnfunc(func_vectormamamam)
{
if (this.noise != "")
{
precache_sound(this.noise);
- soundto(MSG_INIT, this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
}
if(!this.targetfactor)
this.dmgtime = 0.25;
this.dmgtime2 = time;
- if(this.netname == "")
- this.netname = "1 0 0 0 1";
-
if (!InitMovingBrushTrigger(this))
return;
// Savage: Reduce bandwith, critical on e.g. nexdm02
this.effects |= EF_LOWPRECISION;
- this.active = ACTIVE_ACTIVE;
+ this.setactive = func_vectormamamam_setactive;
+ this.setactive(this, ACTIVE_ACTIVE);
+
+ // maybe send sound to new players
+ IL_PUSH(g_initforplayer, this);
+ this.init_for_player = func_vectormamamam_init_for_player;
InitializeEntity(this, func_vectormamamam_findtarget, INITPRIO_FINDTARGET);
}
#pragma once
+
+
+const int PROJECT_ON_TARGETNORMAL = BIT(0);
+const int PROJECT_ON_TARGET2NORMAL = BIT(1);
+const int PROJECT_ON_TARGET3NORMAL = BIT(2);
+const int PROJECT_ON_TARGET4NORMAL = BIT(3);
+
+const float vectormamamam_timestep = 0.1;
void corner_remove(entity this)
{
- if(this.target) { strunzone(this.target); }
- this.target = string_null;
-
- if(this.target2) { strunzone(this.target2); }
- this.target2 = string_null;
-
- if(this.target3) { strunzone(this.target3); }
- this.target3 = string_null;
-
- if(this.target4) { strunzone(this.target4); }
- this.target4 = string_null;
-
- if(this.targetname) { strunzone(this.targetname); }
- this.targetname = string_null;
-
- if(this.platmovetype) { strunzone(this.platmovetype); }
- this.platmovetype = string_null;
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.targetname);
+ strfree(this.platmovetype);
}
NET_HANDLE(ENT_CLIENT_CORNER, bool isnew)
objerror(this, "follow: could not find target/killtarget");
return;
}
- else if(this.spawnflags & 1)
+ else if(this.spawnflags & FOLLOW_ATTACH)
{
// attach
- if(this.spawnflags & 2)
+ if(this.spawnflags & FOLLOW_LOCAL)
{
setattachment(dst, src, this.message);
}
}
else
{
- if(this.spawnflags & 2)
+ if(this.spawnflags & FOLLOW_LOCAL)
{
set_movetype(dst, MOVETYPE_FOLLOW);
dst.aiment = src;
#pragma once
+
+
+const int FOLLOW_ATTACH = BIT(0);
+const int FOLLOW_LOCAL = BIT(1);
vector a;
if(this.enemy)
{
- if(this.spawnflags & 2)
+ if(this.spawnflags & LASER_FINITE)
{
if(this.enemy.origin != this.mangle)
{
this.mangle = this.enemy.origin;
- this.SendFlags |= 2;
+ this.SendFlags |= SF_LASER_UPDATE_TARGET;
}
}
else
if(a != this.mangle)
{
this.mangle = a;
- this.SendFlags |= 2;
+ this.SendFlags |= SF_LASER_UPDATE_TARGET;
}
}
}
if(this.angles != this.mangle)
{
this.mangle = this.angles;
- this.SendFlags |= 2;
+ this.SendFlags |= SF_LASER_UPDATE_TARGET;
}
}
if(this.origin != this.oldorigin)
{
- this.SendFlags |= 1;
+ this.SendFlags |= SF_LASER_UPDATE_ORIGIN;
this.oldorigin = this.origin;
}
}
this.nextthink = time;
- if(!this.state)
+ if(this.active == ACTIVE_NOT)
return;
misc_laser_aim(this);
if(this.enemy)
{
o = this.enemy.origin;
- if (!(this.spawnflags & 2))
- o = this.origin + normalize(o - this.origin) * 32768;
+ if (!(this.spawnflags & LASER_FINITE))
+ o = this.origin + normalize(o - this.origin) * LASER_BEAM_MAXLENGTH;
}
else
{
makevectors(this.mangle);
- o = this.origin + v_forward * 32768;
+ o = this.origin + v_forward * LASER_BEAM_MAXLENGTH;
}
if(this.dmg || this.enemy.target != "")
if(this.dmg)
{
if(this.team)
- if(((this.spawnflags & 8) == 0) == (this.team != hitent.team))
+ if(((this.spawnflags & LASER_INVERT_TEAM) == 0) == (this.team != hitent.team))
return;
if(hitent.takedamage)
Damage(hitent, this, this, ((this.dmg < 0) ? 100000 : (this.dmg * frametime)), DEATH_HURTTRIGGER.m_id, DMG_NOWEP, hitloc, '0 0 0');
}
}
-bool laser_SendEntity(entity this, entity to, float fl)
+bool laser_SendEntity(entity this, entity to, float sendflags)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_LASER);
- fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
- if(this.spawnflags & 2)
- fl |= 0x80;
+ sendflags = sendflags & 0x0F; // use that bit to indicate finite length laser
+ if(this.spawnflags & LASER_FINITE)
+ sendflags |= SF_LASER_FINITE;
if(this.alpha)
- fl |= 0x40;
+ sendflags |= SF_LASER_ALPHA;
if(this.scale != 1 || this.modelscale != 1)
- fl |= 0x20;
- if(this.spawnflags & 4)
- fl |= 0x10;
- WriteByte(MSG_ENTITY, fl);
- if(fl & 1)
+ sendflags |= SF_LASER_SCALE;
+ if(this.spawnflags & LASER_NOTRACE)
+ sendflags |= SF_LASER_NOTRACE;
+ WriteByte(MSG_ENTITY, sendflags);
+ if(sendflags & SF_LASER_UPDATE_ORIGIN)
{
WriteVector(MSG_ENTITY, this.origin);
}
- if(fl & 8)
+ if(sendflags & SF_LASER_UPDATE_EFFECT)
{
- WriteByte(MSG_ENTITY, this.colormod_x * 255.0);
- WriteByte(MSG_ENTITY, this.colormod_y * 255.0);
- WriteByte(MSG_ENTITY, this.colormod_z * 255.0);
- if(fl & 0x40)
+ WriteByte(MSG_ENTITY, this.beam_color.x * 255.0);
+ WriteByte(MSG_ENTITY, this.beam_color.y * 255.0);
+ WriteByte(MSG_ENTITY, this.beam_color.z * 255.0);
+ if(sendflags & SF_LASER_ALPHA)
WriteByte(MSG_ENTITY, this.alpha * 255.0);
- if(fl & 0x20)
+ if(sendflags & SF_LASER_SCALE)
{
WriteByte(MSG_ENTITY, bound(0, this.scale * 16.0, 255));
WriteByte(MSG_ENTITY, bound(0, this.modelscale * 16.0, 255));
}
- if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
- WriteShort(MSG_ENTITY, this.cnt + 1);
+ if((sendflags & SF_LASER_FINITE) || !(sendflags & SF_LASER_NOTRACE)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
+ WriteShort(MSG_ENTITY, this.cnt);
}
- if(fl & 2)
+ if(sendflags & SF_LASER_UPDATE_TARGET)
{
- if(fl & 0x80)
+ if(sendflags & SF_LASER_FINITE)
{
WriteVector(MSG_ENTITY, this.enemy.origin);
}
WriteAngle(MSG_ENTITY, this.mangle_y);
}
}
- if(fl & 4)
- WriteByte(MSG_ENTITY, this.state);
- return 1;
+ if(sendflags & SF_LASER_UPDATE_ACTIVE)
+ WriteByte(MSG_ENTITY, this.active);
+ return true;
}
/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
spawnfunc_target_position where the laser ends
"mdl"
name of beam end effect to use
-"colormod"
+"beam_color"
color of the beam (default: red)
"dmg"
damage per second (-1 for a laser that kills immediately)
*/
-void laser_use(entity this, entity actor, entity trigger)
+
+void laser_setactive(entity this, int act)
{
- this.state = !this.state;
- this.SendFlags |= 4;
- misc_laser_aim(this);
+ int old_status = this.active;
+ if(act == ACTIVE_TOGGLE)
+ {
+ if(this.active == ACTIVE_ACTIVE)
+ {
+ this.active = ACTIVE_NOT;
+ }
+ else
+ {
+ this.active = ACTIVE_ACTIVE;
+ }
+ }
+ else
+ {
+ this.active = act;
+ }
+
+ if (this.active != old_status)
+ {
+ this.SendFlags |= SF_LASER_UPDATE_ACTIVE;
+ misc_laser_aim(this);
+ }
}
-void laser_reset(entity this)
+void laser_use(entity this, entity actor, entity trigger)
{
- if(this.spawnflags & 1)
- this.state = 1;
- else
- this.state = 0;
+ this.setactive(this, ACTIVE_TOGGLE);
}
spawnfunc(misc_laser)
if(this.cnt < 0)
this.cnt = -1;
- if(this.colormod == '0 0 0')
+ if(!this.beam_color && this.colormod)
+ {
+ LOG_WARN("misc_laser uses legacy field 'colormod', please use 'beam_color' instead");
+ this.beam_color = this.colormod;
+ }
+
+ if(this.beam_color == '0 0 0')
+ {
if(!this.alpha)
- this.colormod = '1 0 0';
- if(this.message == "") this.message = "saw the light";
- if (this.message2 == "") this.message2 = "was pushed into a laser by";
- if(!this.scale) this.scale = 1;
- if(!this.modelscale) this.modelscale = 1;
- else if(this.modelscale < 0) this.modelscale = 0;
+ this.beam_color = '1 0 0';
+ }
+
+ if(this.message == "")
+ {
+ this.message = "saw the light";
+ }
+ if (this.message2 == "")
+ {
+ this.message2 = "was pushed into a laser by";
+ }
+ if(!this.scale)
+ {
+ this.scale = 1;
+ }
+ if(!this.modelscale)
+ {
+ this.modelscale = 1;
+ }
+ else if(this.modelscale < 0)
+ {
+ this.modelscale = 0;
+ }
setthink(this, misc_laser_think);
this.nextthink = time;
InitializeEntity(this, misc_laser_init, INITPRIO_FINDTARGET);
Net_LinkEntity(this, false, 0, laser_SendEntity);
+ this.setactive = laser_setactive;
+
IFTARGETED
{
- this.reset = laser_reset;
- this.reset(this);
+ // backwards compatibility
this.use = laser_use;
}
- else
- this.state = 1;
+
+ this.reset = generic_netlinked_reset;
+ this.reset(this);
}
#elif defined(CSQC)
// a laser goes from origin in direction angles
-// it has color 'colormod'
+// it has color 'beam_color'
// and stops when something is in the way
entityclass(Laser);
-class(Laser) .int cnt; // end effect
-class(Laser) .vector colormod;
-class(Laser) .int state; // on-off
-class(Laser) .int count; // flags for the laser
-class(Laser) .vector velocity;
-class(Laser) .float alpha;
-class(Laser) .float scale; // scaling factor of the thickness
-class(Laser) .float modelscale; // scaling factor of the dlight
+classfield(Laser) .int cnt; // end effect
+classfield(Laser) .vector colormod;
+classfield(Laser) .int state; // on-off
+classfield(Laser) .int count; // flags for the laser
+classfield(Laser) .vector velocity; // laser endpoint if it is FINITE
+classfield(Laser) .float alpha;
+classfield(Laser) .float scale; // scaling factor of the thickness
+classfield(Laser) .float modelscale; // scaling factor of the dlight
void Draw_Laser(entity this)
{
- if(!this.state)
+ if(this.active == ACTIVE_NOT)
return;
InterpolateOrigin_Do(this);
- if(this.count & 0x80)
+ if(this.count & SF_LASER_FINITE)
{
- if(this.count & 0x10)
+ if(this.count & SF_LASER_NOTRACE)
{
trace_endpos = this.velocity;
trace_dphitq3surfaceflags = 0;
}
else
{
- if(this.count & 0x10)
+ if(this.count & SF_LASER_NOTRACE)
{
makevectors(this.angles);
- trace_endpos = this.origin + v_forward * 1048576;
+ trace_endpos = this.origin + v_forward * LASER_BEAM_MAXWORLDSIZE;
trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
}
else
{
makevectors(this.angles);
- traceline(this.origin, this.origin + v_forward * 32768, 0, this);
+ traceline(this.origin, this.origin + v_forward * LASER_BEAM_MAXLENGTH, 0, this);
if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
- trace_endpos = this.origin + v_forward * 1048576;
+ trace_endpos = this.origin + v_forward * LASER_BEAM_MAXWORLDSIZE;
}
}
if(this.scale != 0)
{
if(this.alpha)
{
- Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.colormod, this.alpha, DRAWFLAG_NORMAL, view_origin);
+ Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.beam_color, this.alpha, DRAWFLAG_NORMAL, view_origin);
}
else
{
- Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.colormod, 0.5, DRAWFLAG_ADDITIVE, view_origin);
+ Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.beam_color, 0.5, DRAWFLAG_ADDITIVE, view_origin);
}
}
if (!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
{
if(this.cnt >= 0)
__pointparticles(this.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000);
- if(this.colormod != '0 0 0' && this.modelscale != 0)
- adddynamiclight(trace_endpos + trace_plane_normal * 1, this.modelscale, this.colormod * 5);
+ if(this.beam_color != '0 0 0' && this.modelscale != 0)
+ adddynamiclight(trace_endpos + trace_plane_normal * 1, this.modelscale, this.beam_color * 5);
}
}
InterpolateOrigin_Undo(this);
// 30 bytes, or 13 bytes for just moving
- int f = ReadByte();
- this.count = (f & 0xF0);
+ int sendflags = ReadByte();
+ this.count = (sendflags & 0xF0);
- if(this.count & 0x80)
+ if(this.count & SF_LASER_FINITE)
this.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
else
this.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
- if(f & 1)
+ if(sendflags & SF_LASER_UPDATE_ORIGIN)
{
this.origin = ReadVector();
setorigin(this, this.origin);
}
- if(f & 8)
+ if(sendflags & SF_LASER_UPDATE_EFFECT)
{
- this.colormod_x = ReadByte() / 255.0;
- this.colormod_y = ReadByte() / 255.0;
- this.colormod_z = ReadByte() / 255.0;
- if(f & 0x40)
+ this.beam_color.x = ReadByte() / 255.0;
+ this.beam_color.y = ReadByte() / 255.0;
+ this.beam_color.z = ReadByte() / 255.0;
+ if(sendflags & SF_LASER_ALPHA)
this.alpha = ReadByte() / 255.0;
else
this.alpha = 0;
- this.scale = 2;
- this.modelscale = 50;
- if(f & 0x20)
+ this.scale = 2; // NOTE: why 2?
+ this.modelscale = 50; // NOTE: why 50?
+ if(sendflags & SF_LASER_SCALE)
{
this.scale *= ReadByte() / 16.0; // beam radius
this.modelscale *= ReadByte() / 16.0; // dlight radius
}
- if((f & 0x80) || !(f & 0x10))
- this.cnt = ReadShort() - 1; // effect number
+ if((sendflags & SF_LASER_FINITE) || !(sendflags & SF_LASER_NOTRACE))
+ this.cnt = ReadShort(); // effect number
else
this.cnt = 0;
}
- if(f & 2)
+ if(sendflags & SF_LASER_UPDATE_TARGET)
{
- if(f & 0x80)
+ if(sendflags & SF_LASER_FINITE)
{
this.velocity = ReadVector();
}
this.angles_y = ReadAngle();
}
}
- if(f & 4)
- this.state = ReadByte();
+ if(sendflags & SF_LASER_UPDATE_ACTIVE)
+ this.active = ReadByte();
return = true;
#pragma once
+
+
+const int LASER_FINITE = BIT(1);
+const int LASER_NOTRACE = BIT(2);
+const int LASER_INVERT_TEAM = BIT(3);
+
+const int SF_LASER_UPDATE_ORIGIN = BIT(0);
+const int SF_LASER_UPDATE_TARGET = BIT(1);
+const int SF_LASER_UPDATE_ACTIVE = BIT(2);
+const int SF_LASER_UPDATE_EFFECT = BIT(3);
+
+const int SF_LASER_NOTRACE = BIT(4);
+const int SF_LASER_SCALE = BIT(5);
+const int SF_LASER_ALPHA = BIT(6);
+const int SF_LASER_FINITE = BIT(7);
+
+.vector beam_color;
+
+const float LASER_BEAM_MAXLENGTH = 32768; // maximum length of a beam trace
+// TODO: find a better way to do this
+const float LASER_BEAM_MAXWORLDSIZE = 1048576; // to make sure the endpoint of the beam is not visible inside
#ifdef SVQC
-bool teleport_dest_send(entity this, entity to, int sf)
+bool teleport_dest_send(entity this, entity to, int sendflags)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TELEPORT_DEST);
- WriteByte(MSG_ENTITY, sf);
+ WriteByte(MSG_ENTITY, sendflags);
- if(sf & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
WriteByte(MSG_ENTITY, this.cnt);
WriteCoord(MSG_ENTITY, this.speed);
void teleport_dest_link(entity this)
{
Net_LinkEntity(this, false, 0, teleport_dest_send);
- this.SendFlags |= 1; // update
+ this.SendFlags |= SF_TRIGGER_INIT;
}
spawnfunc(info_teleport_destination)
void teleport_dest_remove(entity this)
{
- //if(this.classname)
- //strunzone(this.classname);
- //this.classname = string_null;
-
- if(this.targetname)
- strunzone(this.targetname);
- this.targetname = string_null;
+ // strfree(this.classname);
+ strfree(this.targetname);
}
NET_HANDLE(ENT_CLIENT_TELEPORT_DEST, bool isnew)
{
- int sf = ReadByte();
+ int sendflags = ReadByte();
- if(sf & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
this.classname = "info_teleport_destination";
this.cnt = ReadByte();
void plat_hit_top(entity this)
{
_sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
- this.state = 1;
+ this.state = STATE_TOP;
setthink(this, plat_go_down);
this.nextthink = this.ltime + 3;
void plat_hit_bottom(entity this)
{
_sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
- this.state = 2;
+ this.state = STATE_BOTTOM;
}
void plat_go_down(entity this)
{
_sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
- this.state = 3;
+ this.state = STATE_DOWN;
SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, plat_hit_bottom);
}
void plat_go_up(entity this)
{
_sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
- this.state = 4;
+ this.state = STATE_UP;
SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, plat_hit_top);
}
return;
#endif
- if (this.enemy.state == 2) {
+ if (this.enemy.state == STATE_BOTTOM) {
plat_go_up(this.enemy);
- } else if (this.enemy.state == 1)
+ } else if (this.enemy.state == STATE_TOP)
this.enemy.nextthink = this.enemy.ltime + 1;
}
return;
#endif
- if (this.enemy.state == 1) {
+ if (this.enemy.state == STATE_TOP) {
entity e = this.enemy;
plat_go_down(e);
}
void plat_crush(entity this, entity blocker)
{
- if((this.spawnflags & 4) && (blocker.takedamage != DAMAGE_NO))
+ if((this.spawnflags & CRUSH) && (blocker.takedamage != DAMAGE_NO))
{ // KIll Kill Kill!!
#ifdef SVQC
Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, blocker.origin, '0 0 0');
}
#endif
- if (this.state == 4)
+ if (this.state == STATE_UP)
plat_go_down (this);
- else if (this.state == 3)
+ else if (this.state == STATE_DOWN)
plat_go_up (this);
// when in other states, then the plat_crush event came delayed after
// plat state already had changed
void plat_use(entity this, entity actor, entity trigger)
{
this.use = func_null;
- if (this.state != 4)
+ if (this.state != STATE_UP)
objerror (this, "plat_use: not in up state");
plat_go_down(this);
}
+// WARNING: backwards compatibility because people don't use already existing fields :(
+// TODO: Check if any maps use these fields and remove these fields if it doesn't break maps
.string sound1, sound2;
void plat_reset(entity this)
IFTARGETED
{
setorigin(this, this.pos1);
- this.state = 4;
+ this.state = STATE_UP;
this.use = plat_use;
}
else
{
setorigin(this, this.pos2);
- this.state = 2;
+ this.state = STATE_BOTTOM;
this.use = plat_trigger_use;
}
#pragma once
+
+const int PLAT_LOW_TRIGGER = BIT(0);
+
.float dmgtime2;
void plat_center_touch(entity this, entity toucher);
void plat_go_up(entity this);
void plat_go_down(entity this);
void plat_crush(entity this, entity blocker);
-const float PLAT_LOW_TRIGGER = 1;
.float dmg;
// derivative: delta + 2 * delta2 (e.g. for angle positioning)
entity own = this.owner;
setthink(own, this.think1);
+ // set the owner's reference to this entity to NULL
+ own.move_controller = NULL;
delete(this);
getthink(own)(own);
}
return;
}
+ // delete the previous controller, otherwise changing movement midway is glitchy
+ if (this.move_controller != NULL)
+ {
+ delete(this.move_controller);
+ }
controller = new(SUB_CalcMove_controller);
controller.owner = this;
+ this.move_controller = controller;
controller.platmovetype = this.platmovetype;
controller.platmovetype_start = this.platmovetype_start;
controller.platmovetype_end = this.platmovetype_end;
#pragma once
+#include "defs.qh"
void SUB_SetFade (entity ent, float when, float fading_time);
void SUB_VanishOrRemove (entity ent);
.vector dest1, dest2;
+.entity move_controller;
+
#ifdef CSQC
// this stuff is defined in the server side engine VM, so we must define it separately here
.float takedamage;
-const float DAMAGE_NO = 0;
-const float DAMAGE_YES = 1;
-const float DAMAGE_AIM = 2;
-
-float STATE_TOP = 0;
-float STATE_BOTTOM = 1;
-float STATE_UP = 2;
-float STATE_DOWN = 3;
+const int DAMAGE_NO = 0;
+const int DAMAGE_YES = 1;
+const int DAMAGE_AIM = 2;
.string noise, noise1, noise2, noise3; // contains names of wavs to play
void target_changelevel_use(entity this, entity actor, entity trigger)
{
- if(this.spawnflags & 2)
+ if(this.spawnflags & CHANGELEVEL_MULTIPLAYER)
{
// simply don't react if a non-player triggers it
if(!IS_PLAYER(actor)) { return; }
localcmd(strcat("changelevel ", this.chmap, "\n"));
}
+/*target_changelevel
+Target to change/end level
+KEYS:
+chmap: map to switch to, leave empty for endmatch
+gametype: gametype for the next map
+count: fraction of real players that need to trigger this entity for levelchange
+SPAWNFLAGS:
+CHANGELEVEL_MULTIPLAYER: multiplayer support
+*/
+
spawnfunc(target_changelevel)
{
this.use = target_changelevel_use;
- if(!this.count) { this.count = 0.7; }
+ if(!this.count)
+ {
+ this.count = 0.7;
+ }
}
#endif
#pragma once
+
+
+const int CHANGELEVEL_MULTIPLAYER = BIT(1);
spawnfunc(target_levelwarp)
{
+ // this.cnt is index (starting from 1) of the campaign level to warp to
+ // 0 means next level
this.use = target_levelwarp_use;
}
#endif
#ifdef SVQC
IntrusiveList g_targetmusic_list;
-STATIC_INIT(g_targetmusic_list) { g_targetmusic_list = IL_NEW(); }
+STATIC_INIT(g_targetmusic_list)
+{
+ g_targetmusic_list = IL_NEW();
+}
// values:
// volume
}
void target_music_reset(entity this)
{
- if (this.targetname == "") target_music_sendto(this, MSG_ALL, 1);
+ if (this.targetname == "")
+ {
+ target_music_sendto(this, MSG_ALL, true);
+ }
}
void target_music_kill()
{
{
it.volume = 0;
if (it.targetname == "")
- target_music_sendto(it, MSG_ALL, 1);
+ target_music_sendto(it, MSG_ALL, true);
else
- target_music_sendto(it, MSG_ALL, 0);
+ target_music_sendto(it, MSG_ALL, false);
});
}
void target_music_use(entity this, entity actor, entity trigger)
if(IS_REAL_CLIENT(actor))
{
msg_entity = actor;
- target_music_sendto(this, MSG_ONE, 1);
+ target_music_sendto(this, MSG_ONE, true);
}
FOREACH_CLIENT(IS_SPEC(it) && it.enemy == actor, {
msg_entity = it;
- target_music_sendto(this, MSG_ONE, 1);
+ target_music_sendto(this, MSG_ONE, true);
});
}
spawnfunc(target_music)
this.volume = 1;
IL_PUSH(g_targetmusic_list, this);
if(this.targetname == "")
- target_music_sendto(this, MSG_INIT, 1);
+ target_music_sendto(this, MSG_INIT, true);
else
- target_music_sendto(this, MSG_INIT, 0);
+ target_music_sendto(this, MSG_INIT, false);
}
void TargetMusic_RestoreGame()
{
IL_EACH(g_targetmusic_list, true,
{
if(it.targetname == "")
- target_music_sendto(it, MSG_INIT, 1);
+ target_music_sendto(it, MSG_INIT, true);
else
- target_music_sendto(it, MSG_INIT, 0);
+ target_music_sendto(it, MSG_INIT, false);
});
}
// values:
// targetname
// fade_time
// spawnflags:
-// 1 = START_OFF
-// when triggered, it is disabled/enabled for everyone
-bool trigger_music_SendEntity(entity this, entity to, float sf)
+// START_DISABLED
+// can be disabled/enabled for everyone with relays
+bool trigger_music_SendEntity(entity this, entity to, int sendflags)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
- sf &= ~0x80;
- if(this.cnt)
- sf |= 0x80;
- WriteByte(MSG_ENTITY, sf);
- if(sf & 4)
+ WriteByte(MSG_ENTITY, sendflags);
+ if(sendflags & SF_MUSIC_ORIGIN)
{
WriteVector(MSG_ENTITY, this.origin);
}
- if(sf & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
if(this.model != "null")
{
WriteByte(MSG_ENTITY, this.fade_rate * 16.0);
WriteString(MSG_ENTITY, this.noise);
}
- return 1;
+ if(sendflags & SF_TRIGGER_UPDATE)
+ {
+ WriteByte(MSG_ENTITY, this.active);
+ }
+ return true;
}
void trigger_music_reset(entity this)
{
- this.cnt = !(this.spawnflags & 1);
- this.SendFlags |= 0x80;
-}
-void trigger_music_use(entity this, entity actor, entity trigger)
-{
- this.cnt = !this.cnt;
- this.SendFlags |= 0x80;
+ if(this.spawnflags & START_DISABLED)
+ {
+ this.setactive(this, ACTIVE_NOT);
+ }
+ else
+ {
+ this.setactive(this, ACTIVE_ACTIVE);
+ }
}
+
spawnfunc(trigger_music)
{
- if(this.model != "") _setmodel(this, this.model);
- if(!this.volume) this.volume = 1;
+ if(this.model != "")
+ {
+ _setmodel(this, this.model);
+ }
+ if(!this.volume)
+ {
+ this.volume = 1;
+ }
if(!this.modelindex)
{
setorigin(this, this.origin + this.mins);
setsize(this, '0 0 0', this.maxs - this.mins);
}
- trigger_music_reset(this);
- this.use = trigger_music_use;
+ this.setactive = generic_netlinked_setactive;
+ this.use = generic_netlinked_legacy_use; // backwards compatibility
this.reset = trigger_music_reset;
+ this.reset(this);
Net_LinkEntity(this, false, 0, trigger_music_SendEntity);
}
{
// run AFTER all the thinks!
entity best = music_default;
- if (music_target && time < music_target.lifetime) best = music_target;
- if (music_trigger) best = music_trigger;
+ if (music_target && time < music_target.lifetime)
+ {
+ best = music_target;
+ }
+ if (music_trigger)
+ {
+ best = music_trigger;
+ }
LL_EACH(TargetMusic_list, it.noise, {
const float vol0 = (getsoundtime(it, CH_BGM_SINGLE) >= 0) ? it.lastvol : -1;
if (it == best)
if (vol != vol0)
{
if(vol0 < 0)
- _sound(it, CH_BGM_SINGLE, it.noise, vol, ATTEN_NONE); // restart
+ sound7(it, CH_BGM_SINGLE, it.noise, vol, ATTEN_NONE, 0, BIT(4)); // restart
else
- _sound(it, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+ sound7(it, CH_BGM_SINGLE, "", vol, ATTEN_NONE, 0, BIT(4));
it.lastvol = vol;
}
});
}
if(e.noise != noi)
{
- if(e.noise)
- strunzone(e.noise);
- e.noise = strzone(noi);
+ strcpy(e.noise, noi);
precache_sound(e.noise);
_sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
if(getsoundtime(e, CH_BGM_SINGLE) < 0)
{
LOG_TRACEF("Cannot initialize sound %s", e.noise);
- strunzone(e.noise);
- e.noise = string_null;
+ strfree(e.noise);
}
}
e.volume = vol;
void Ent_TriggerMusic_Think(entity this)
{
- if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, this, NULL))
+ if(this.active == ACTIVE_NOT)
+ {
+ return;
+ }
+ vector org = (csqcplayer) ? csqcplayer.origin : view_origin;
+ if(WarpZoneLib_BoxTouchesBrush(org + STAT(PL_MIN), org + STAT(PL_MAX), this, NULL))
{
music_trigger = this;
}
- this.nextthink = time;
}
void Ent_TriggerMusic_Remove(entity this)
{
- if(this.noise)
- strunzone(this.noise);
- this.noise = string_null;
+ strfree(this.noise);
}
NET_HANDLE(ENT_CLIENT_TRIGGER_MUSIC, bool isnew)
{
- int f = ReadByte();
- if(f & 4)
+ int sendflags = ReadByte();
+ if(sendflags & SF_MUSIC_ORIGIN)
{
this.origin = ReadVector();
}
- if(f & 1)
+ if(sendflags & SF_TRIGGER_INIT)
{
this.modelindex = ReadShort();
if(this.modelindex)
this.fade_time = ReadByte() / 16.0;
this.fade_rate = ReadByte() / 16.0;
string s = this.noise;
- if(this.noise)
- strunzone(this.noise);
- this.noise = strzone(ReadString());
+ strcpy(this.noise, ReadString());
if(this.noise != s)
{
precache_sound(this.noise);
- _sound(this, CH_BGM_SINGLE, this.noise, 0, ATTEN_NONE);
+ sound7(this, CH_BGM_SINGLE, this.noise, 0, ATTEN_NONE, 0, BIT(4));
if(getsoundtime(this, CH_BGM_SINGLE) < 0)
{
- LOG_TRACEF("Cannot initialize sound %s", this.noise);
- strunzone(this.noise);
- this.noise = string_null;
+ LOG_WARNF("Cannot initialize sound %s", this.noise);
+ strfree(this.noise);
}
}
}
+ if(sendflags & SF_TRIGGER_UPDATE)
+ {
+ this.active = ReadByte();
+ }
setorigin(this, this.origin);
setsize(this, this.mins, this.maxs);
- this.cnt = 1;
- setthink(this, Ent_TriggerMusic_Think);
- this.nextthink = time;
+ this.draw = Ent_TriggerMusic_Think;
+ if(isnew)
+ {
+ LL_PUSH(TargetMusic_list, this);
+ IL_PUSH(g_drawables, this);
+ }
return true;
}
.float lifetime;
+const int SF_MUSIC_ORIGIN = BIT(2);
+
#ifdef CSQC
float music_disabled;
entity music_default;
// FIXME also control bgmvolume here, to not require a target_music for the default track.
entityclass(TargetMusic);
-class(TargetMusic) .int state;
-class(TargetMusic) .float lastvol;
+classfield(TargetMusic) .int state;
+classfield(TargetMusic) .float lastvol;
void TargetMusic_Advance();
// "classname" "target_spawn"
// "message" "fieldname value fieldname value ..."
// "spawnflags"
-// 1 = call the spawn function
-// 2 = trigger on map load
+// ON_MAPLOAD = trigger on map load
float target_spawn_initialized;
.void(entity this) target_spawn_spawnfunc;
void target_spawn_spawnfirst(entity this)
{
entity act = this.target_spawn_activator;
- if(this.spawnflags & 2)
+ if(this.spawnflags & ON_MAPLOAD)
target_spawn_use(this, act, NULL);
}
else
snd = this.noise;
_sound(this, CH_TRIGGER_SINGLE, snd, VOL_BASE * this.volume, this.atten);
- if(this.spawnflags & 3)
+ if(this.spawnflags & (SPEAKER_LOOPED_ON + SPEAKER_LOOPED_OFF))
this.use = target_speaker_use_off;
}
void target_speaker_use_off(entity this, entity actor, entity trigger)
}
void target_speaker_reset(entity this)
{
- if(this.spawnflags & 1) // LOOPED_ON
+ if(this.spawnflags & SPEAKER_LOOPED_ON)
{
if(this.use == target_speaker_use_on)
target_speaker_use_on(this, NULL, NULL);
}
- else if(this.spawnflags & 2)
+ else if(this.spawnflags & SPEAKER_LOOPED_OFF)
{
if(this.use == target_speaker_use_off)
target_speaker_use_off(this, NULL, NULL);
if(this.noise)
precache_sound (this.noise);
- if(!this.atten && !(this.spawnflags & 4))
+ if(!this.atten && (this.spawnflags & SPEAKER_GLOBAL))
+ {
+ LOG_WARN("target_speaker uses legacy spawnflag GLOBAL (BIT(2)), please set atten to -1 instead");
+ this.atten = -1;
+ }
+
+ if(!this.atten)
{
IFTARGETED
this.atten = ATTEN_NORM;
IFTARGETED
{
- if(this.spawnflags & 8) // ACTIVATOR
+ if(this.spawnflags & SPEAKER_ACTIVATOR)
this.use = target_speaker_use_activator;
- else if(this.spawnflags & 1) // LOOPED_ON
+ else if(this.spawnflags & SPEAKER_LOOPED_ON)
{
target_speaker_use_on(this, NULL, NULL);
this.reset = target_speaker_reset;
}
- else if(this.spawnflags & 2) // LOOPED_OFF
+ else if(this.spawnflags & SPEAKER_LOOPED_OFF)
{
this.use = target_speaker_use_on;
this.reset = target_speaker_reset;
else
this.use = target_speaker_use_on;
}
- else if(this.spawnflags & 1) // LOOPED_ON
+ else if(this.spawnflags & SPEAKER_LOOPED_ON)
{
ambientsound (this.origin, this.noise, VOL_BASE * this.volume, this.atten);
delete(this);
}
- else if(this.spawnflags & 2) // LOOPED_OFF
+ else if(this.spawnflags & SPEAKER_LOOPED_OFF)
{
objerror(this, "This sound entity can never be activated");
}
#pragma once
+
+
+const int SPEAKER_LOOPED_ON = BIT(0);
+const int SPEAKER_LOOPED_OFF = BIT(1);
+const int SPEAKER_GLOBAL = BIT(2); // legacy, set speaker atten to -1 instead
+const int SPEAKER_ACTIVATOR = BIT(3);
#pragma once
+#include "defs.qh"
IntrusiveList g_teleporters;
STATIC_INIT(g_teleporters) { g_teleporters = IL_NEW(); }
.entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+const int TELEPORT_FLAG_SOUND = BIT(0);
+const int TELEPORT_FLAG_PARTICLES = BIT(1);
+const int TELEPORT_FLAG_TDEATH = BIT(2);
+const int TELEPORT_FLAG_FORCE_TDEATH = BIT(3);
#define TELEPORT_FLAGS_WARPZONE 0
#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
// types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+const int TELEPORT_NORMAL = 1; // play sounds/effects etc
+const int TELEPORT_SIMPLE = 2; // only do teleport, nothing special
entity Simple_TeleportPlayer(entity teleporter, entity player);
if (this.count < 0)
return;
- bool doactivate = (this.spawnflags & 4);
+ bool doactivate = (this.spawnflags & COUNTER_FIRE_AT_COUNT);
if (this.count == 0)
{
this.count = this.cnt;
}
-/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
+/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT
Acts as an intermediary for an action that takes multiple inputs.
If nomessage is not set, it will print "1 more.. " etc when triggered and "sequence complete" when finished.
+If COUNTER_FIRE_AT_COUNT is set, it will also fire all of its targets at countdown, making it behave like trigger_mulitple with limited shots
If respawntime is set, it will re-enable itself after the time once the sequence has been completed
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
+After the counter has been triggered "count" times (default 2), it will fire all of its targets.
*/
spawnfunc(trigger_counter)
{
#pragma once
+
+
+const int COUNTER_FIRE_AT_COUNT = BIT(2);
spawnfunc(trigger_flipflop)
{
- if(this.spawnflags & 1)
- this.state = 1;
+ if(this.spawnflags & START_ENABLED)
+ {
+ this.state = true;
+ }
this.use = flipflop_use;
this.reset = spawnfunc_trigger_flipflop; // perfect resetter
}
}
}
+// legacy
void trigger_gravity_use(entity this, entity actor, entity trigger)
{
- this.state = !this.state;
+ this.setactive(this, ACTIVE_TOGGLE);
}
void trigger_gravity_touch(entity this, entity toucher)
{
float g;
- if(this.state != true)
+ if(this.active == ACTIVE_NOT)
return;
EXACTTRIGGER_TOUCH(this, toucher);
g = this.gravity;
- if (!(this.spawnflags & 1))
+ if (!(this.spawnflags & GRAVITY_STICKY))
{
if(toucher.trigger_gravity_check)
{
if(this == toucher.trigger_gravity_check.enemy)
{
// same?
+ // NOTE: see explanation in trigger_gravity_check_think
toucher.trigger_gravity_check.count = 2; // gravity one more frame...
return;
}
if(this.noise != "")
precache_sound(this.noise);
- this.state = true;
+ this.active = ACTIVE_ACTIVE;
+ this.setactive = generic_setactive;
IFTARGETED
{
+ // legacy use
this.use = trigger_gravity_use;
- if(this.spawnflags & 2)
- this.state = false;
+ if(this.spawnflags & GRAVITY_START_DISABLED)
+ this.active = ACTIVE_NOT;
}
}
#endif
#pragma once
+
+
+const int GRAVITY_STICKY = BIT(0); // keep gravity multiplier even after exiting the trigger_gravity
+const int GRAVITY_START_DISABLED = BIT(1);
// only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
if (toucher.iscreature)
{
- if (toucher.takedamage)
- if (!IS_DEAD(toucher))
- if (toucher.triggerhealtime < time)
+ if (toucher.takedamage && !IS_DEAD(toucher) && toucher.triggerhealtime < time)
{
bool is_trigger = this.targetname == "";
if(is_trigger)
if(this.delay > 0)
toucher.triggerhealtime = time + this.delay;
- bool playthesound = (this.spawnflags & 4);
+ bool playthesound = (this.spawnflags & HEAL_SOUND_ALWAYS);
if (toucher.health < this.max_health)
{
playthesound = true;
#pragma once
+
+
+const int HEAL_SOUND_ALWAYS = BIT(2);
return;
if(this.team)
- if(((this.spawnflags & 4) == 0) == (this.team != toucher.team))
+ if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
return;
// only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
/*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
Any object touching this will be hurt
set dmg to damage amount
-defalt dmg = 5
+default dmg = 1000
*/
.entity trigger_hurt_next;
entity trigger_hurt_last;
trigger_hurt_last = this;
}
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
+bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end)
{
entity th;
for(th = trigger_hurt_first; th; th = th.trigger_hurt_next)
- if(tracebox_hits_box(start, mi, ma, end, th.absmin, th.absmax))
+ if(tracebox_hits_box(start, e_min, e_max, end, th.absmin, th.absmax))
return true;
return false;
#include "impulse.qh"
// targeted (directional) mode
-void trigger_impulse_touch1(entity this, entity toucher)
+void trigger_impulse_touch_directional(entity this, entity toucher)
{
entity targ;
float pushdeltatime;
return;
}
- str = min(this.radius, vlen(this.origin - toucher.origin));
-
- if(this.falloff == 1)
- str = (str / this.radius) * this.strength;
- else if(this.falloff == 2)
- str = (1 - (str / this.radius)) * this.strength;
- else
- str = this.strength;
+ // falloff is not supported because radius is always 0 in directional mode
+ str = this.strength;
pushdeltatime = time - toucher.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
+ if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+ {
+ pushdeltatime = 0;
+ }
toucher.lastpushtime = time;
- if(!pushdeltatime) return;
+ if(!pushdeltatime)
+ {
+ return;
+ }
- if(this.spawnflags & 64)
+ if(this.spawnflags & IMPULSE_DIRECTIONAL_SPEEDTARGET)
{
float addspeed = str - toucher.velocity * normalize(targ.origin - this.origin);
if (addspeed > 0)
{
- float accelspeed = min(8 * pushdeltatime * str, addspeed);
+ float accelspeed = min(IMPULSE_DIRECTIONAL_MAX_ACCEL_FACTOR * pushdeltatime * str, addspeed);
toucher.velocity += accelspeed * normalize(targ.origin - this.origin);
}
}
}
// Directionless (accelerator/decelerator) mode
-void trigger_impulse_touch2(entity this, entity toucher)
+void trigger_impulse_touch_accel(entity this, entity toucher)
{
float pushdeltatime;
EXACTTRIGGER_TOUCH(this, toucher);
pushdeltatime = time - toucher.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
+ if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+ {
+ pushdeltatime = 0;
+ }
toucher.lastpushtime = time;
- if(!pushdeltatime) return;
+ if(!pushdeltatime)
+ {
+ return;
+ }
// div0: ticrate independent, 1 = identity (not 20)
toucher.velocity = toucher.velocity * (this.strength ** pushdeltatime);
}
// Spherical (gravity/repulsor) mode
-void trigger_impulse_touch3(entity this, entity toucher)
+void trigger_impulse_touch_radial(entity this, entity toucher)
{
float pushdeltatime;
float str;
EXACTTRIGGER_TOUCH(this, toucher);
pushdeltatime = time - toucher.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
+ if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+ {
+ pushdeltatime = 0;
+ }
toucher.lastpushtime = time;
- if(!pushdeltatime) return;
+ if(!pushdeltatime)
+ {
+ return;
+ }
setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
str = min(this.radius, vlen(this.origin - toucher.origin));
- if(this.falloff == 1)
+ if(this.falloff == FALLOFF_LINEAR)
str = (1 - str / this.radius) * this.strength; // 1 in the inside
- else if(this.falloff == 2)
+ else if(this.falloff == FALLOFF_LINEAR_INV)
str = (str / this.radius) * this.strength; // 0 in the inside
else
str = this.strength;
REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_IMPULSE)
/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
+Force field
-------- KEYS --------
target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
If not, this trigger acts like a damper/accelerator field.
-strength : This is how mutch force to add in the direction of .target each second
- when .target is set. If not, this is hoe mutch to slow down/accelerate
- someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
+strength : This is how much force to add in the direction of .target each second
+ when .target is set. If not, this is how much to slow down/accelerate
+ something cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
-radius : If set, act as a spherical device rather then a liniar one.
+radius : If set, act as a spherical device rather then a linear one.
falloff : 0 = none, 1 = liniar, 2 = inverted liniar
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
- WriteInt24_t(MSG_ENTITY, this.spawnflags);
+ WriteByte(MSG_ENTITY, this.spawnflags);
WriteCoord(MSG_ENTITY, this.radius);
WriteCoord(MSG_ENTITY, this.strength);
WriteByte(MSG_ENTITY, this.falloff);
if(this.radius)
{
- if(!this.strength) this.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
+ if(!this.strength)
+ {
+ this.strength = IMPULSE_DEFAULT_RADIAL_STRENGTH * autocvar_g_triggerimpulse_radial_multiplier;
+ }
setorigin(this, this.origin);
setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
- settouch(this, trigger_impulse_touch3);
+ settouch(this, trigger_impulse_touch_radial);
}
else
{
if(this.target)
{
- if(!this.strength) this.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
- settouch(this, trigger_impulse_touch1);
+ if(!this.strength)
+ {
+ this.strength = IMPULSE_DEFAULT_DIRECTIONAL_STRENGTH * autocvar_g_triggerimpulse_directional_multiplier;
+ }
+ settouch(this, trigger_impulse_touch_directional);
}
else
{
- if(!this.strength) this.strength = 0.9;
+ if(!this.strength)
+ {
+ this.strength = IMPULSE_DEFAULT_ACCEL_STRENGTH;
+ }
this.strength = (this.strength ** autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
- settouch(this, trigger_impulse_touch2);
+ settouch(this, trigger_impulse_touch_accel);
}
}
#elif defined(CSQC)
NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
{
- this.spawnflags = ReadInt24_t();
+ this.spawnflags = ReadByte();
this.radius = ReadCoord();
this.strength = ReadCoord();
this.falloff = ReadByte();
this.entremove = trigger_remove_generic;
this.move_time = time;
- if (this.radius) { settouch(this, trigger_impulse_touch3); }
- else if (this.target) { settouch(this, trigger_impulse_touch1); }
- else { settouch(this, trigger_impulse_touch2); }
+ if (this.radius)
+ {
+ settouch(this, trigger_impulse_touch_radial);
+ }
+ else if (this.target)
+ {
+ settouch(this, trigger_impulse_touch_directional);
+ }
+ else
+ {
+ settouch(this, trigger_impulse_touch_accel);
+ }
}
#endif
// tZorks trigger impulse / gravity
.float radius;
-.float falloff;
+.int falloff;
.float strength;
.float lastpushtime;
+
+const int FALLOFF_NO = 0;
+const int FALLOFF_LINEAR = 1;
+const int FALLOFF_LINEAR_INV = 2;
+
+const int IMPULSE_DIRECTIONAL_SPEEDTARGET = BIT(6);
+
+const float IMPULSE_DEFAULT_RADIAL_STRENGTH = 2000;
+const float IMPULSE_DEFAULT_DIRECTIONAL_STRENGTH = 950;
+const float IMPULSE_DEFAULT_ACCEL_STRENGTH = 0.9;
+
+const float IMPULSE_MAX_PUSHDELTATIME = 0.15;
+
+const float IMPULSE_DIRECTIONAL_MAX_ACCEL_FACTOR = 8;
#include "jumppads.qh"
// TODO: split target_push and put it in the target folder
#ifdef SVQC
-#include "jumppads.qh"
#include <common/physics/movetypes/movetypes.qh>
void trigger_push_use(entity this, entity actor, entity trigger)
if(teamplay)
{
this.team = actor.team;
- this.SendFlags |= 2;
+ this.SendFlags |= SF_TRIGGER_UPDATE;
}
}
#endif
return;
if(this.team)
- if(((this.spawnflags & 4) == 0) == (DIFF_TEAM(this, toucher)))
+ if(((this.spawnflags & INVERT_TEAMS) == 0) == (DIFF_TEAM(this, toucher)))
return;
EXACTTRIGGER_TOUCH(this, toucher);
{
// first calculate a typical start point for the jump
vector org = (this.absmin + this.absmax) * 0.5;
- org.z = this.absmax.z - PL_MIN_CONST.z - 10;
+ org.z = this.absmax.z - PL_MIN_CONST.z - 7;
if (this.target)
{
void trigger_push_updatelink(entity this)
{
- this.SendFlags |= 1;
+ this.SendFlags |= SF_TRIGGER_INIT;
}
void trigger_push_link(entity this)
target_push_init(this); // normal push target behaviour can be combined with a legacy pusher?
}
-spawnfunc(target_push) { target_push_init2(this); }
-spawnfunc(info_notnull) { target_push_init(this); }
-spawnfunc(target_position) { target_push_init(this); }
+spawnfunc(target_push)
+{
+ target_push_init2(this);
+}
+
+spawnfunc(info_notnull)
+{
+ target_push_init(this);
+}
+spawnfunc(target_position)
+{
+ target_push_init(this);
+}
#elif defined(CSQC)
NET_HANDLE(ENT_CLIENT_TRIGGER_PUSH, bool isnew)
{
this.classname = "jumppad";
- int mytm = ReadByte(); if(mytm) { this.team = mytm - 1; }
+ int mytm = ReadByte();
+ if(mytm)
+ {
+ this.team = mytm - 1;
+ }
this.spawnflags = ReadInt24_t();
this.active = ReadByte();
this.height = ReadCoord();
void target_push_remove(entity this)
{
- //if(this.classname)
- //strunzone(this.classname);
- //this.classname = string_null;
-
- if(this.targetname)
- strunzone(this.targetname);
- this.targetname = string_null;
+ // strfree(this.classname);
+ strfree(this.targetname);
}
NET_HANDLE(ENT_CLIENT_TARGET_PUSH, bool isnew)
#pragma once
+
+const int PUSH_ONCE = BIT(0); // legacy, deactivate with relay instead
+const int PUSH_SILENT = BIT(1); // not used?
+
IntrusiveList g_jumppads;
STATIC_INIT(g_jumppads) { g_jumppads = IL_NEW(); }
-const float PUSH_ONCE = 1;
-const float PUSH_SILENT = 2;
-
.float pushltime;
.float istypefrag;
.float height;
#elif defined(CSQC)
void keylock_remove(entity this)
{
- if(this.target) { strunzone(this.target); }
- this.target = string_null;
-
- if(this.target2) { strunzone(this.target2); }
- this.target2 = string_null;
-
- if(this.target3) { strunzone(this.target3); }
- this.target3 = string_null;
-
- if(this.target4) { strunzone(this.target4); }
- this.target4 = string_null;
-
- if(this.killtarget) { strunzone(this.killtarget); }
- this.killtarget = string_null;
-
- if(this.targetname) { strunzone(this.targetname); }
- this.targetname = string_null;
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.killtarget);
+ strfree(this.targetname);
}
NET_HANDLE(ENT_CLIENT_KEYLOCK, bool isnew)
magicear_matched = false;
dotrigger = ((IS_PLAYER(source)) && (!IS_DEAD(source)) && ((ear.radius == 0) || (vdist(source.origin - ear.origin, <=, ear.radius))));
- domatch = ((ear.spawnflags & 32) || dotrigger);
+ domatch = ((ear.spawnflags & MAGICEAR_REPLACE_OUTSIDE) || dotrigger);
if (!domatch)
return msgin;
if (!msgin)
{
// we are in TUBA mode!
- if (!(ear.spawnflags & 256))
+ if (!(ear.spawnflags & MAGICEAR_TUBA))
return msgin;
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
- if(!W_Tuba_HasPlayed(source, weaponentity, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
+ if(!W_Tuba_HasPlayed(source, weaponentity, ear.message, ear.movedir_x, !(ear.spawnflags & MAGICEAR_TUBA_EXACTPITCH), ear.movedir_y, ear.movedir_z))
return msgin;
}
return msgin;
}
- if(ear.spawnflags & 256) // ENOTUBA
+ if(ear.spawnflags & MAGICEAR_TUBA) // ENOTUBA
return msgin;
if(privatesay)
{
- if(ear.spawnflags & 4)
+ if(ear.spawnflags & MAGICEAR_IGNORE_TELL)
return msgin;
}
else
{
if(!teamsay)
- if(ear.spawnflags & 1)
+ if(ear.spawnflags & MAGICEAR_IGNORE_SAY)
return msgin;
if(teamsay > 0)
- if(ear.spawnflags & 2)
+ if(ear.spawnflags & MAGICEAR_IGNORE_TEAMSAY)
return msgin;
if(teamsay < 0)
- if(ear.spawnflags & 8)
+ if(ear.spawnflags & MAGICEAR_IGNORE_INVALIDTELL)
return msgin;
}
matchstart = -1;
l = strlen(ear.message);
- if(ear.spawnflags & 128)
+ if(ear.spawnflags & MAGICEAR_NODECOLORIZE)
msg = msgin;
else
msg = strdecolorize(msgin);
ear.message = savemessage;
}
- if(ear.spawnflags & 16)
+ if(ear.spawnflags & MAGICEAR_REPLACE_WHOLE_MESSAGE)
{
return ear.netname;
}
for(ear = magicears; ear; ear = ear.enemy)
{
msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
- if(!(ear.spawnflags & 64))
+ if(!(ear.spawnflags & MAGICEAR_CONTINUE))
if(magicear_matched)
return msgout;
msgin = msgout;
#pragma once
+
+
+const int MAGICEAR_IGNORE_SAY = BIT(0);
+const int MAGICEAR_IGNORE_TEAMSAY = BIT(1);
+const int MAGICEAR_IGNORE_TELL = BIT(2);
+const int MAGICEAR_IGNORE_INVALIDTELL = BIT(3);
+const int MAGICEAR_REPLACE_WHOLE_MESSAGE = BIT(4);
+const int MAGICEAR_REPLACE_OUTSIDE = BIT(5);
+const int MAGICEAR_CONTINUE = BIT(6);
+const int MAGICEAR_NODECOLORIZE = BIT(7);
+const int MAGICEAR_TUBA = BIT(8);
+const int MAGICEAR_TUBA_EXACTPITCH = BIT(9);
{
if(!this.wait)
this.wait = 1;
- if(this.spawnflags & 1)
+ if(this.spawnflags & MONOFLOP_FIXED)
this.use = monoflop_fixed_use;
else
this.use = monoflop_use;
#pragma once
+
+
+const int MONOFLOP_FIXED = BIT(0);
return; // allready been triggered
}
- if(this.spawnflags & 16384)
- if(!IS_PLAYER(this.enemy))
+ if(this.spawnflags & ONLY_PLAYERS && !IS_PLAYER(this.enemy))
+ {
return; // only players
+ }
+ // TODO: restructure this so that trigger_secret is more independent
if (this.classname == "trigger_secret")
{
if (!IS_PLAYER(this.enemy))
}
if (this.noise)
+ {
_sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+ }
-// don't trigger again until reset
+ // don't trigger again until reset
this.takedamage = DAMAGE_NO;
SUB_UseTargets(this, this.enemy, this.goalentity);
void multi_touch(entity this, entity toucher)
{
- if(!(this.spawnflags & 2))
- if(!toucher.iscreature)
- return;
+ if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
+ {
+ return;
+ }
if(this.team)
- if(((this.spawnflags & 4) == 0) == (this.team != toucher.team))
+ {
+ if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
+ {
return;
+ }
+ }
-// if the trigger has an angles field, check player's facing direction
+ // if the trigger has an angles field, check player's facing direction
if (this.movedir != '0 0 0')
{
makevectors (toucher.angles);
// if the trigger has pressed keys, check that the player is pressing those keys
if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
- if(!(CS(toucher).pressedkeys & this.pressedkeys))
- return;
+ {
+ if(!(CS(toucher).pressedkeys & this.pressedkeys))
+ {
+ return;
+ }
+ }
EXACTTRIGGER_TOUCH(this, toucher);
{
if(!this.takedamage)
return;
- if(this.spawnflags & DOOR_NOSPLASH)
+ if(this.spawnflags & NOSPLASH)
if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
return;
if(this.team)
- if(((this.spawnflags & 4) == 0) == (this.team != attacker.team))
+ if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
return;
this.health = this.health - damage;
if (this.health <= 0)
void multivibrator_reset(entity this)
{
- if(!(this.spawnflags & 1))
+ if(!(this.spawnflags & START_ENABLED))
this.nextthink = 0; // wait for a trigger event
else
this.nextthink = max(1, time);
}
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
+/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
"Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
-------- KEYS --------
target: trigger all entities with this targetname when it goes off
wait: "on" cycle time (default: 1)
respawntime: "off" cycle time (default: same as wait)
-------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
+START_ENABLED: assume it is already turned on (when targeted)
*/
spawnfunc(trigger_multivibrator)
{
this.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
}
-spawnfunc(target_relay) { spawnfunc_trigger_relay(this); }
+spawnfunc(target_relay)
+{
+ spawnfunc_trigger_relay(this);
+}
#endif
else
{
//bprint("Not using setactive\n");
- if(this.cnt == ACTIVE_TOGGLE)
- if(trg.active == ACTIVE_ACTIVE)
- trg.active = ACTIVE_NOT;
- else
- trg.active = ACTIVE_ACTIVE;
- else
- trg.active = this.cnt;
+ generic_setactive(trg, this.cnt);
}
}
}
// TODO make this generic AND faster than nextent()ing through all, if somehow possible
n = (cvar_string(this.netname) == cvar_string(this.message));
- if(this.spawnflags & 1)
+ if(this.spawnflags & RELAYIF_NEGATE)
n = !n;
if(n)
#pragma once
+
+
+const int RELAYIF_NEGATE = BIT(0);
{
if(actor.team)
{
- if(this.spawnflags & 2)
+ if(this.spawnflags & RELAYTEAMCHECK_INVERT)
{
if(DIFF_TEAM(actor, this))
SUB_UseTargets(this, actor, trigger);
}
else
{
- if(this.spawnflags & 1)
+ if(this.spawnflags & RELAYTEAMCHECK_NOTEAM)
SUB_UseTargets(this, actor, trigger);
}
}
#pragma once
+
+
+const int RELAYTEAMCHECK_NOTEAM = BIT(0);
+const int RELAYTEAMCHECK_INVERT = BIT(1);
return false;
if(this.team)
- if(((this.spawnflags & 4) == 0) == (DIFF_TEAM(this, player)))
+ if(((this.spawnflags & INVERT_TEAMS) == 0) == (DIFF_TEAM(this, player)))
return false;
return true;
string s = this.target; this.target = string_null;
SUB_UseTargets(this, player, player); // TODO: should we be using toucher for trigger too?
- if (!this.target) this.target = s;
+ if (!this.target)
+ {
+ this.target = s;
+ }
SUB_UseTargets(e, player, player);
}
this.classname = "trigger_teleport";
if(isnew)
IL_PUSH(g_teleporters, this);
- int mytm = ReadByte(); if(mytm) { this.team = mytm - 1; }
+ int mytm = ReadByte();
+ if(mytm)
+ {
+ this.team = mytm - 1;
+ }
this.spawnflags = ReadInt24_t();
this.active = ReadByte();
this.speed = ReadCoord();
}
// compatibility
-spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
+spawnfunc(target_viewlocation)
+{
+ spawnfunc_target_viewlocation_start(this);
+}
#elif defined(CSQC)
#pragma once
-.entity viewloc;
const int VIEWLOC_NOSIDESCROLL = BIT(0); // NOTE: currently unimplemented
const int VIEWLOC_FREEAIM = BIT(1);
const int VIEWLOC_FREEMOVE = BIT(2);
+.entity viewloc;
+
#ifdef CSQC
.entity goalentity;
.entity enemy;
}
#ifdef SVQC
+void generic_setactive(entity this, int act)
+{
+ if(act == ACTIVE_TOGGLE)
+ {
+ if(this.active == ACTIVE_ACTIVE)
+ {
+ this.active = ACTIVE_NOT;
+ }
+ else
+ {
+ this.active = ACTIVE_ACTIVE;
+ }
+ }
+ else
+ {
+ this.active = act;
+ }
+}
+
+void generic_netlinked_setactive(entity this, int act)
+{
+ int old_status = this.active;
+ generic_setactive(this, act);
+
+ if (this.active != old_status)
+ {
+ this.SendFlags |= SF_TRIGGER_UPDATE;
+ }
+}
+
+void generic_netlinked_reset(entity this)
+{
+ IFTARGETED
+ {
+ if(this.spawnflags & START_ENABLED)
+ {
+ this.active = ACTIVE_ACTIVE;
+ }
+ else
+ {
+ this.active = ACTIVE_NOT;
+ }
+ }
+ else
+ {
+ this.active = ACTIVE_ACTIVE;
+ }
+
+ this.SendFlags |= SF_TRIGGER_UPDATE;
+}
+
+// Compatibility with old maps
+void generic_netlinked_legacy_use(entity this, entity actor, entity trigger)
+{
+ LOG_WARNF("Entity %s was (de)activated by a trigger, please update map to use relays", this.targetname);
+ this.setactive(this, ACTIVE_TOGGLE);
+}
bool autocvar_g_triggers_debug = true;
if(withtarget)
{
- if(this.target) { strunzone(this.target); }
- if(this.target2) { strunzone(this.target2); }
- if(this.target3) { strunzone(this.target3); }
- if(this.target4) { strunzone(this.target4); }
- if(this.targetname) { strunzone(this.targetname); }
- if(this.killtarget) { strunzone(this.killtarget); }
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.targetname);
+ strfree(this.killtarget);
int targbits = ReadByte();
void trigger_remove_generic(entity this)
{
- if(this.target) { strunzone(this.target); }
- this.target = string_null;
-
- if(this.target2) { strunzone(this.target2); }
- this.target2 = string_null;
-
- if(this.target3) { strunzone(this.target3); }
- this.target3 = string_null;
-
- if(this.target4) { strunzone(this.target4); }
- this.target4 = string_null;
-
- if(this.targetname) { strunzone(this.targetname); }
- this.target = string_null;
-
- if(this.killtarget) { strunzone(this.killtarget); }
- this.killtarget = string_null;
+ strfree(this.target);
+ strfree(this.target2);
+ strfree(this.target3);
+ strfree(this.target4);
+ strfree(this.targetname);
+ strfree(this.killtarget);
}
#endif
#pragma once
-
-const float SF_TRIGGER_INIT = 1;
-const float SF_TRIGGER_UPDATE = 2;
-const float SF_TRIGGER_RESET = 4;
-
-const float SPAWNFLAG_NOMESSAGE = 1;
-const float SPAWNFLAG_NOTOUCH = 1;
+#include "defs.qh"
.bool pushable;
void target_voicescript_clear(entity pl);
void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger);
+
+void generic_setactive(entity this, int act);
+// generic methods for netlinked entities
+void generic_netlinked_reset(entity this);
+void generic_netlinked_setactive(entity this, int act);
+// WARNING: DON'T USE, ONLY TO KEEP COMPATIBILITY BECAUSE OF SWITCH FROM .state TO .alive!!!!
+void generic_netlinked_legacy_use(entity this, entity actor, entity trigger);
#endif
.float sub_target_used;
.float active;
.string target;
.string targetname;
-
-const int ACTIVE_NOT = 0;
-const int ACTIVE_ACTIVE = 1;
-const int ACTIVE_IDLE = 2;
-const int ACTIVE_BUSY = 2;
-const int ACTIVE_TOGGLE = 3;
#endif
METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this, entity it))
{
- if(g_instagib)
+ if(autocvar_g_instagib)
{
.entity weaponentity = weaponentities[0]; // TODO: unhardcode
FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * max_shot_distance, 10000000000,
METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret thistur, entity it))
{
- if (g_instagib) {
+ if (autocvar_g_instagib) {
.entity weaponentity = weaponentities[0]; // TODO: unhardcode
FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * max_shot_distance, 10000000000,
800, 0, 0, 0, 0, DEATH_TURRET_PLASMA.m_id);
{
vector mi, ma;
- if(mi_shortname)
- strunzone(mi_shortname);
- mi_shortname = mapname;
- if(!strcasecmp(substring(mi_shortname, 0, 5), "maps/"))
- mi_shortname = substring(mi_shortname, 5, strlen(mi_shortname) - 5);
- if(!strcasecmp(substring(mi_shortname, strlen(mi_shortname) - 4, 4), ".bsp"))
- mi_shortname = substring(mi_shortname, 0, strlen(mi_shortname) - 4);
- mi_shortname = strzone(mi_shortname);
+ string s = mapname;
+ if(!strcasecmp(substring(s, 0, 5), "maps/"))
+ s = substring(s, 5, strlen(s) - 5);
+ if(!strcasecmp(substring(s, strlen(s) - 4, 4), ".bsp"))
+ s = substring(s, 0, strlen(s) - 4);
+ strcpy(mi_shortname, s);
#ifdef CSQC
mi = world.mins;
if(to_execute_next_frame)
{
localcmd("\n", to_execute_next_frame, "\n");
- strunzone(to_execute_next_frame);
- to_execute_next_frame = string_null;
+ strfree(to_execute_next_frame);
}
}
void queue_to_execute_next_frame(string s)
if(to_execute_next_frame)
{
s = strcat(s, "\n", to_execute_next_frame);
- strunzone(to_execute_next_frame);
}
- to_execute_next_frame = strzone(s);
+ strcpy(to_execute_next_frame, s);
}
.float FindConnectedComponent_processing;
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg);
entityclass(Hook);
-class(Hook) .entity HookType; // ENT_CLIENT_*
-class(Hook) .vector origin;
-class(Hook) .vector velocity;
-class(Hook) .float HookSilent;
-class(Hook) .float HookRange;
+classfield(Hook) .entity HookType; // ENT_CLIENT_*
+classfield(Hook) .vector origin;
+classfield(Hook) .vector velocity;
+classfield(Hook) .float HookSilent;
+classfield(Hook) .float HookRange;
string Draw_GrapplingHook_trace_callback_tex;
float Draw_GrapplingHook_trace_callback_rnd;
Draw_GrapplingHook_trace_callback_rnd += 0.25 * vlen(hit - start) / 8;
}
-class(Hook) .float teleport_time;
+classfield(Hook) .float teleport_time;
void Draw_GrapplingHook(entity this)
{
vector a, b, atrans;
#ifdef CSQC
entityclass(Tuba);
-class(Tuba) .int note;
-class(Tuba) .bool tuba_attenuate;
-class(Tuba) .float tuba_volume;
-class(Tuba) .float tuba_volume_initial;
-class(Tuba) .int tuba_instrument;
+classfield(Tuba) .int note;
+classfield(Tuba) .bool tuba_attenuate;
+classfield(Tuba) .float tuba_volume;
+classfield(Tuba) .float tuba_volume_initial;
+classfield(Tuba) .int tuba_instrument;
#endif
if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
W_RocketMinsta_Explosion(actor, weaponentity, trace_endpos);
- W_DecreaseAmmo(thiswep, actor, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)), weaponentity);
+ W_DecreaseAmmo(thiswep, actor, ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)), weaponentity);
}
void W_RocketMinsta_Laser_Explode (entity this, entity directhitentity)
}
METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
- float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+ float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
// if the laser uses load, we also consider its ammo for reloading
if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.(weaponentity).clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
thiswep.wr_reload(thiswep, actor, weaponentity);
}
METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
- float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+ float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= vaporizer_ammo;
ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
return ammo_amount;
}
METHOD(Vaporizer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
{
- float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+ float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
float used_ammo;
if(WEP_CVAR_SEC(vaporizer, ammo))
used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo));
float maxspeed_mod = (!this.in_swamp) ? 1 : this.swamp_slowdown; // cvar("g_balance_swamp_moverate");
// conveyors: first fix velocity
- if (this.conveyor.state) { this.velocity -= this.conveyor.movedir; }
+ if (this.conveyor.active) { this.velocity -= this.conveyor.movedir; }
MUTATOR_CALLHOOK(PlayerPhysics, this, dt);
if (!IS_PLAYER(this)) {
LABEL(end)
if (IS_ONGROUND(this)) { this.lastground = time; }
// conveyors: then break velocity again
- if (this.conveyor.state) { this.velocity += this.conveyor.movedir; }
+ if (this.conveyor.active) { this.velocity += this.conveyor.movedir; }
this.lastflags = this.flags;
this.lastclassname = this.classname;
{
WarpZone_PlayerPhysics_FixVAngle(this);
Physics_UpdateStats(this);
+ PM_ClientMovement_UpdateStatus(this);
}
bool sys_phys_override(entity this, float dt)
#define bool float
#endif
+#ifndef QCC_SUPPORT_ACCUMULATE
+ #warning "QCC does not support accumulate, may not compile correctly"
+ #define ACCUMULATE
+#else
+ #define ACCUMULATE [[accumulate]]
+#endif
+
#ifndef QCC_SUPPORT_ERASEABLE
#define ERASEABLE
#else
#define ERASEABLE [[eraseable]]
#endif
+#ifndef QCC_SUPPORT_ALIAS
+ #warning "QCC does not support alias, may not compile correctly"
+ #define ALIAS(var)
+#else
+ #define ALIAS(var) [[alias(var)]]
+#endif
+
#include <dpdefs/pre.qh>
#if defined(CSQC)
#include <dpdefs/post.qh>
+#ifndef QCC_SUPPORT_POW
+ #define pow(a, b) pow(a, b)
+#else
+ #define pow(a, b) ((a) ** (b))
+#endif
+
#include "self.qh"
#define USING(name, T) typedef T name
#ifdef QCC_SUPPORT_ACCUMULATE
#define ACCUMULATE_FUNCTION(func, otherfunc) \
- [[accumulate]] void func() \
+ ACCUMULATE void func() \
{ \
otherfunc(); \
}
#endif
#endif
+#ifndef QCC_SUPPORT_ALIAS
+ #ifdef GMQCC
+ #define QCC_SUPPORT_ALIAS
+ #endif
+#endif
+
+#ifndef QCC_SUPPORT_POW
+ #ifdef GMQCC
+ #define QCC_SUPPORT_POW
+ #endif
+#endif
+
#ifdef GMQCC
#define LABEL(id) :id
#else
// e.g.: AUTOCVAR(mycvar, float, 2.5, "cvar description")
#define __AUTOCVAR(file, archive, var, type, desc, default) \
- [[accumulate]] void RegisterCvars(void(string, string, string, bool, string) f) \
+ ACCUMULATE void RegisterCvars(void(string, string, string, bool, string) f) \
{ \
f( #var, repr_cvar_##type(default), desc, archive, file); \
} \
#include "self.qh"
entityclass(Defer);
- class(Defer).entity owner;
- class(Defer).void(entity) defer_func;
+ classfield(Defer).entity owner;
+ classfield(Defer).void(entity) defer_func;
/** Remove entity */
void SUB_Remove(entity this)
GENERIC_COMMAND(mx, "Send a matrix command") {
switch (argv(1)) {
case "user":
- if (matrix_user) strunzone(matrix_user);
- matrix_user = strzone(substring(command, argv_start_index(2), -1));
+ strcpy(matrix_user, substring(command, argv_start_index(2), -1));
break;
case "token":
- if (matrix_access_token) strunzone(matrix_access_token);
- matrix_access_token = strzone(substring(command, argv_start_index(2), -1));
+ strcpy(matrix_access_token, substring(command, argv_start_index(2), -1));
break;
case "messages":
MX_Messages(string_null);
fh.url_verb = "PUT";
fh.url_content_type = "application/json";
url_fputs(fh, sprintf("{\"msgtype\": \"m.text\", \"body\": \"%s\"}", pass.message));
- strunzone(pass.message); delete(pass);
+ strfree(pass.message);
+ delete(pass);
url_fclose(fh);
break;
}
#include "p99.qh"
#define OVERLOAD(F, ...) P99_IF_EMPTY(__VA_ARGS__)(P99_PASTE2(F, _00)())(P99_PASTE3(F, _, P00_NARG(__VA_ARGS__))(__VA_ARGS__))
- /** for use within a macro */
+ /** for use within macros */
#define OVERLOAD_(F, ...) P99_IF_EMPTY(__VA_ARGS__)(P99_PASTE2(F, _00)())(P99_PASTE3(F, _, P00_NARG(__VA_ARGS__))(__VA_ARGS__))
+ #define OVERLOAD__(F, ...) P99_IF_EMPTY(__VA_ARGS__)(P99_PASTE2(F, _00)())(P99_PASTE3(F, _, P00_NARG(__VA_ARGS__))(__VA_ARGS__))
#else
#define EVAL(...) __VA_ARGS__
- #define OVERLOAD_(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
#define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+ #define OVERLOAD_(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+ #define OVERLOAD__(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
#endif
#if defined(CSQC)
#ifdef CSQC
#define REGISTER_NET_LINKED(id) \
- [[accumulate]] NET_HANDLE(id, bool isnew) \
+ ACCUMULATE NET_HANDLE(id, bool isnew) \
{ \
this = __self; \
this.sourceLoc = __FILE__ ":" STR(__LINE__); \
#ifdef SVQC
const int MSG_ENTITY = 5;
- .int Version; // deprecated, use SendFlags
.int SendFlags;
IntrusiveList g_uncustomizables;
{
if (g_buf == "") return;
localcmd("\ncmd c2s \"", strreplace("$", "$$", g_buf), "\"\n");
- strunzone(g_buf);
- g_buf = string_null;
+ strfree(g_buf);
}
#endif
string s = string_null;
yenc_single(b, s);
string tmp = strcat(g_buf, s);
- if (g_buf) strunzone(g_buf);
- g_buf = strzone(tmp);
+ strcpy(g_buf, tmp);
}
void WriteShort(int to, int b)
{
// noises "usually" start in the range -1..1
entityclass(Noise);
-class(Noise).float noise_baccum;
-class(Noise).float noise_paccum;
-class(Noise).float noise_paccum2;
-class(Noise).float noise_paccum3;
-class(Noise).float noise_bstate;
+classfield(Noise).float noise_baccum;
+classfield(Noise).float noise_paccum;
+classfield(Noise).float noise_paccum2;
+classfield(Noise).float noise_paccum3;
+classfield(Noise).float noise_bstate;
ERASEABLE
float Noise_Brown(entity e, float dt)
#include "static.qh"
.vector origin;
+
.bool pure_data;
-/** @deprecated use new_pure or NEW(class) */
-#define make_pure(e) \
- MACRO_BEGIN \
- { \
- (e).pure_data = true; \
- } MACRO_END
-#define make_impure(e) \
- MACRO_BEGIN \
- { \
- (e).pure_data = false; \
- } MACRO_END
#define is_pure(e) ((e).pure_data)
+/** @deprecated use new_pure or NEW(class) */
+#define make_pure(e) MACRO_BEGIN \
+ (e).pure_data = true; \
+MACRO_END
+#define make_impure(e) MACRO_BEGIN \
+ (e).pure_data = false; \
+MACRO_END
.string classname;
/** Location entity was spawned from in source */
#define entityclass_1(name) entityclass_2(name, Object)
#ifndef QCC_SUPPORT_ENTITYCLASS
#define entityclass_2(name, base) USING(name, entity)
- #define class(name)
+ #define classfield(name)
#define _new(class, pure) __spawn( #class, __FILE__ ":" STR(__LINE__), pure)
#else
#define entityclass_2(name, base) entityclass name : base {}
- #define class(name) [[class(name)]]
+ #define classfield(name) [[class(name)]]
#define _new(class, pure) ((class) __spawn( #class, __FILE__ ":" STR(__LINE__), pure))
#endif
/** entities you care about seeing (.origin works) */
#define new_pure(class) _new(class, true)
#define spawn() __spawn("entity", __FILE__ ":" STR(__LINE__), false)
-[[accumulate]] void ONREMOVE(entity this) {}
+ACCUMULATE void ONREMOVE(entity this) {}
#ifndef SVQC
#define delete_fn builtin_remove
#endif
+.void(entity this) dtor;
#define delete(this) MACRO_BEGIN { \
entity _this = (this); \
void(entity) _dtor = _this.dtor; \
}
// Classes have a `spawn##cname(entity)` constructor
-// The parameter is used across [[accumulate]] functions
+// The parameter is used across ACCUMULATE functions
.bool transmute;
} \
MACRO_END
-#define CONSTRUCTOR(cname, ...) \
- cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) \
- { \
- return = this; \
- } \
- [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
+#define CLASS(...) EVAL_CLASS(OVERLOAD__(CLASS, __VA_ARGS__))
+#define EVAL_CLASS(...) __VA_ARGS__
+
+#define ATTRIB(...) EVAL_ATTRIB(OVERLOAD_(ATTRIB, __VA_ARGS__))
+#define EVAL_ATTRIB(...) __VA_ARGS__
+
+#ifdef QCC_SUPPORT_CLASS
+
+#warning "QCC_SUPPORT_CLASS not implemented"
+
+#define CLASS_1(name) CLASS_2(name, entity)
+#define CLASS_2(name, base) class name : base {
+
+#define INIT(class) void class::class()
+#define CONSTRUCTOR(class, ...) void class::class(__VA_ARGS__)
+#define DESTRUCTOR(class) class::~class()
+
+#define SUPER(class) super
+
+#define ATTRIB_3(class, name, T) T name
+#define ATTRIB_4(class, name, T, val) ATTRIB_3(class, name, T) = val
+#define STATIC_ATTRIB(class, name, T, val) static T name = val
+
+#define ATTRIB_STRZONE(class, name, T, val) T name = val
+#define STATIC_ATTRIB_STRZONE(class, name, T, val) static T name = val
+
+#define ATTRIBARRAY(class, name, T, val) T name[val]
+
+#define METHOD(class, name, prototype) virtual void class::name()
+#define STATIC_METHOD(class, name, prototype) static void class::name()
+
+#define ENDCLASS(class) };
+
+#else
+
+#define CLASS_1(cname) CLASS_2(cname, )
+#define CLASS_2(cname, base) \
+ entityclass(cname, base); \
+ classfield(cname).bool instanceOf##cname; \
+ DEBUG_STUFF(cname) \
+ VTBL(cname, base) \
+ _INIT_STATIC(cname) \
+ { \
+ if (cname##_vtbl && !this.transmute) \
+ { \
+ copyentity(cname##_vtbl, this); \
+ return; \
+ } \
+ spawn##base##_static(this); \
+ this.instanceOf##cname = true; \
+ } \
+ INIT(cname) \
+ { \
+ /* Only statically initialize the current class, it contains everything it inherits */ \
+ if (cname##_vtbl.vtblname == this.classname) \
+ { \
+ spawn##cname##_static(this); \
+ this.transmute = false; \
+ this.classname = #cname; \
+ this.vtblname = string_null; \
+ this.vtblbase = cname##_vtbl; \
+ } \
+ spawn##base##_1(this); \
+ }
+
+#define INIT(cname) \
+ ACCUMULATE cname spawn##cname##_1(cname this)
+
+#define CONSTRUCTOR(cname, ...) \
+ cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) \
+ { \
+ return = this; \
+ } \
+ ACCUMULATE cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
+
+#define DESTRUCTOR(cname) \
+ STATIC_METHOD(cname, dtorimpl, void(cname this)); \
+ METHOD(cname, dtor, void(cname this)) \
+ { \
+ METHOD_REFERENCE(cname, dtorimpl)(this); \
+ this.instanceOf##cname = false; \
+ entity super = SUPER(cname); \
+ if (super != cname##_vtbl) super.dtor(this); \
+ } \
+ STATIC_METHOD(cname, dtorimpl, void(cname this))
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+
+#define ATTRIB_3(cname, name, type) classfield(cname) .type name
+#define ATTRIB_4(cname, name, type, val) \
+ ATTRIB_3(cname, name, type); \
+ INIT(cname) \
+ { \
+ noref bool strzone; /* Error on strzone() calls. */ \
+ this.name = val; \
+ } \
+ ATTRIB_3(cname, name, type)
+
+#define STATIC_ATTRIB(cname, name, type, val) \
+ type cname##_##name; \
+ _INIT_STATIC(cname) \
+ { \
+ noref bool strzone; /* Error on strzone() calls. */ \
+ cname##_##name = val; \
+ }
+
+// cleanup potentially zoned strings from base classes
+#define ATTRIB_STRZONE(cname, name, type, val) \
+ classfield(cname).type name; \
+ INIT(cname) \
+ { \
+ strcpy(this.name, val); \
+ }
+
+#define STATIC_ATTRIB_STRZONE(cname, name, type, val) \
+ type cname##_##name; \
+ _INIT_STATIC(cname) \
+ { \
+ strcpy(cname##_##name, val); \
+ }
+
+#define ATTRIBARRAY(cname, name, type, cnt) \
+ classfield(cname) .type name[cnt]
+
+#define METHOD(cname, name, prototype) \
+ STATIC_METHOD(cname, name, prototype); \
+ classfield(cname) .prototype name; \
+ _INIT_STATIC(cname) \
+ { \
+ this.name = METHOD_REFERENCE(cname, name); \
+ } \
+ STATIC_METHOD(cname, name, prototype)
+
+#define STATIC_METHOD(cname, name, prototype) \
+ prototype METHOD_REFERENCE(cname, name)
+
+#define ENDCLASS(cname) \
+ INIT(cname) \
+ { \
+ return this; \
+ }
+
+// impl
.string vtblname;
.entity vtblbase;
} \
ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
-#define _INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
-#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
+#define _INIT_STATIC(cname) ACCUMULATE void spawn##cname##_static(cname this)
#if NDEBUG
#define DEBUG_STUFF(cname)
#else
#define DEBUG_STUFF(cname) \
- bool is_##cname(entity e) { return e.instanceOf##cname; } \
- void isnt_##cname(entity e) { eprint(e); }
+ ERASEABLE bool is_##cname(entity e) { return e.instanceOf##cname; } \
+ ERASEABLE void isnt_##cname(entity e) { eprint(e); }
#endif
-
-#define CLASS(cname, base) \
- entityclass(cname, base); \
- class(cname).bool instanceOf##cname; \
- DEBUG_STUFF(cname) \
- VTBL(cname, base) \
- _INIT_STATIC(cname) \
- { \
- if (cname##_vtbl && !this.transmute)\
- { \
- copyentity(cname##_vtbl, this); \
- return; \
- } \
- spawn##base##_static(this); \
- this.instanceOf##cname = true; \
- } \
- INIT(cname) \
- { \
- /* Only statically initialize the current class, it contains everything it inherits */ \
- if (cname##_vtbl.vtblname == this.classname) \
- { \
- spawn##cname##_static(this); \
- this.transmute = false; \
- this.classname = #cname; \
- this.vtblname = string_null; \
- this.vtblbase = cname##_vtbl; \
- } \
- spawn##base##_1(this); \
- }
-
#define METHOD_REFERENCE(cname, name) \
cname##_##name
-#define STATIC_METHOD(cname, name, prototype) \
- prototype METHOD_REFERENCE(cname, name)
-
-#define METHOD(cname, name, prototype) \
- STATIC_METHOD(cname, name, prototype); \
- class(cname) .prototype name; \
- _INIT_STATIC(cname) \
- { \
- this.name = METHOD_REFERENCE(cname, name); \
- } \
- STATIC_METHOD(cname, name, prototype)
-
-#define DESTRUCTOR(cname) \
- STATIC_METHOD(cname, dtorimpl, void(cname this)); \
- METHOD(cname, dtor, void(cname this)) \
- { \
- METHOD_REFERENCE(cname, dtorimpl)(this); \
- this.instanceOf##cname = false; \
- entity super = SUPER(cname); \
- if (super != cname##_vtbl) super.dtor(this); \
- } \
- STATIC_METHOD(cname, dtorimpl, void(cname this))
-
-#define ATTRIB(...) EVAL_ATTRIB(OVERLOAD_(ATTRIB, __VA_ARGS__))
-#define EVAL_ATTRIB(...) __VA_ARGS__
-#define ATTRIB_3(cname, name, type) class(cname) .type name
-#define ATTRIB_4(cname, name, type, val) \
- ATTRIB_3(cname, name, type); \
- INIT(cname) \
- { \
- noref bool strzone; /* Error on strzone() calls. */ \
- this.name = val; \
- } \
- ATTRIB_3(cname, name, type)
-
-#define STATIC_ATTRIB(cname, name, type, val) \
- type cname##_##name; \
- _INIT_STATIC(cname) \
- { \
- noref bool strzone; /* Error on strzone() calls. */ \
- cname##_##name = val; \
- }
-
-// cleanup potentially zoned strings from base classes
-
-#define ATTRIB_STRZONE(cname, name, type, val) \
- class(cname).type name; \
- INIT(cname) \
- { \
- if (this.name) \
- strunzone(this.name); \
- this.name = strzone(val); \
- }
-
-#define STATIC_ATTRIB_STRZONE(cname, name, type, val) \
- type cname##_##name; \
- _INIT_STATIC(cname) \
- { \
- if (cname##_##name) \
- strunzone(cname##_##name); \
- cname##_##name = val; \
- }
-
-#define ATTRIBARRAY(cname, name, type, cnt) \
- class(cname) .type name[cnt]
-
-#define ENDCLASS(cname) \
- INIT(cname) \
- { \
- return this; \
- }
-
-#define SUPER(cname) (cname##_vtbl.vtblbase)
+#endif
#define spawn_static(this)
#define spawn_1(this)
#define _vtbl NULL
-CLASS(Object, );
+CLASS(Object)
DESTRUCTOR(Object) { builtin_remove(this); }
#define remove(this) delete(this)
METHOD(Object, describe, string(Object this))
*/
#define REGISTRY(id, max) \
void Register##id(); \
- [[accumulate]] void REGISTRY_DEPENDS_(id) {} \
+ ACCUMULATE void REGISTRY_DEPENDS_(id) {} \
REGISTRY_BEGIN(id) {} \
REGISTRY_END(id) {} \
void _Register##id() {} \
#define REGISTRY_DEPENDS_(id) Register##id##_Depends()
/** Called before initializing a registry. */
-#define REGISTRY_BEGIN(id) [[accumulate]] void REGISTRY_BEGIN_(id) { noref void() f = Register##id; } void REGISTRY_BEGIN_(id)
+#define REGISTRY_BEGIN(id) ACCUMULATE void REGISTRY_BEGIN_(id) { noref void() f = Register##id; } void REGISTRY_BEGIN_(id)
#define REGISTRY_BEGIN_(id) Register##id##_First()
/** Called after initializing a registry. */
-#define REGISTRY_END(id) [[accumulate]] void REGISTRY_END_(id) { noref void() f = Register##id; } void REGISTRY_END_(id)
+#define REGISTRY_END(id) ACCUMULATE void REGISTRY_END_(id) { noref void() f = Register##id; } void REGISTRY_END_(id)
#define REGISTRY_END_(id) Register##id##_Done()
REGISTRY(Registries, BITS(8))
REGISTRY_PUSH(registry, fld, e); \
} MACRO_END
-#define REGISTER_INIT(id) [[accumulate]] void Register_##id##_init(entity this)
+#define REGISTER_INIT(id) ACCUMULATE void Register_##id##_init(entity this)
/** internal next pointer */
#define REGISTRY_NEXT enemy
#define REGISTRY_HASH(id) Registry_hash_##id
ERASEABLE
-[[accumulate]] void Registry_check(string r, string server) { }
+ACCUMULATE void Registry_check(string r, string server) { }
ERASEABLE
-[[accumulate]] void Registry_send_all() { }
+ACCUMULATE void Registry_send_all() { }
#ifdef SVQC
void Registry_send(string id, string hash);
#define REPLICATE(...) EVAL_REPLICATE(OVERLOAD(REPLICATE, __VA_ARGS__))
#define EVAL_REPLICATE(...) __VA_ARGS__
- [[accumulate]] void ReplicateVars(entity this, entity store, string thisname, int i) {}
+ ACCUMULATE void ReplicateVars(entity this, entity store, string thisname, int i) {}
#define REPLICATE_3(fld, type, var) REPLICATE_4(fld, type, var, )
#define REPLICATE_4(fld, type, var, func) REPLICATE_##type(fld, var, func)
#define REPLICATE_string(fld, var, func) \
REPLICATE_7(fld, string, var, , \
- { if (field) strunzone(field); field = strzone(it); }, \
- { if (field) strunzone(field); field = string_null; }, \
+ { strcpy(field, it); }, \
+ { strfree(field); }, \
{ \
/* also initialize to the default value of func when requesting cvars */ \
string s = func(field); \
if (s != field) \
{ \
- strunzone(field); \
- field = strzone(s); \
+ strcpy(field, s); \
} \
})
#define REPLICATE_float(fld, var, func) REPLICATE_7(fld, float, var, func, { field = stof(it); }, , )
// Step 2: const self
#if 1
#define self (RVALUE, self)
- [[alias("self")]] entity __self;
+ ALIAS("self") entity __self;
#define setself(s) (__self = s)
#define WITHSELF(value, block) WITH(entity, __self, value, (RVALUE, block))
#endif
entityclass(Sort);
// .float(entity,entity) sort_cmp;
-class(Sort).entity chain, sort_next, sort_prev;
+classfield(Sort).entity chain, sort_next, sort_prev;
entity Sort_Spawn();
#define spawnfunc_1(id) spawnfunc_2(id, FIELDS_UNION)
#define spawnfunc_2(id, whitelist) \
void __spawnfunc_##id(entity this); \
- [[accumulate]] void spawnfunc_##id(entity this) \
+ ACCUMULATE void spawnfunc_##id(entity this) \
{ \
if (!__spawnfunc_first) { \
__spawnfunc_first = true; \
FIELD_SCALAR(fld, bgmscriptsustain) \
FIELD_SCALAR(fld, bgmscript) \
FIELD_SCALAR(fld, button0) \
+ FIELD_SCALAR(fld, chmap) \
FIELD_SCALAR(fld, cnt) \
FIELD_SCALAR(fld, colormap) \
FIELD_SCALAR(fld, count) \
FIELD_SCALAR(fld, dmg_force) \
FIELD_SCALAR(fld, dmg_radius) \
FIELD_SCALAR(fld, effects) \
+ FIELD_SCALAR(fld, falloff) \
FIELD_SCALAR(fld, flags) \
FIELD_SCALAR(fld, fog) \
FIELD_SCALAR(fld, frags) \
FIELD_SCALAR(fld, frame) \
+ FIELD_SCALAR(fld, gametype) \
FIELD_SCALAR(fld, gametypefilter) \
FIELD_SCALAR(fld, geomtype) \
FIELD_SCALAR(fld, gravity) \
FIELD_SCALAR(fld, noalign) \
FIELD_SCALAR(fld, noise1) \
FIELD_SCALAR(fld, noise2) \
+ FIELD_SCALAR(fld, noise3) \
FIELD_SCALAR(fld, noise) \
FIELD_SCALAR(fld, phase) \
FIELD_SCALAR(fld, platmovetype) \
FIELD_SCALAR(fld, target_random) \
FIELD_SCALAR(fld, target_range) \
FIELD_SCALAR(fld, team) \
+ FIELD_SCALAR(fld, trigger_reverse) \
FIELD_SCALAR(fld, turret_scale_health) \
FIELD_SCALAR(fld, turret_scale_range) \
FIELD_SCALAR(fld, turret_scale_respawn) \
FIELD_VEC(fld, absmin) \
FIELD_VEC(fld, angles) \
FIELD_VEC(fld, avelocity) \
+ FIELD_VEC(fld, beam_color)\
FIELD_VEC(fld, debrisavelocityjitter) \
FIELD_VEC(fld, debrisvelocity) \
FIELD_VEC(fld, debrisvelocityjitter) \
}
#define _STATIC_INIT(func, where) \
- [[accumulate]] void _static_##func() { profile(#func); } \
+ ACCUMULATE void _static_##func##profile() { profile(#func); } \
+ ACCUMULATE_FUNCTION(where, _static_##func##profile) \
+ ACCUMULATE void _static_##func(); \
ACCUMULATE_FUNCTION(where, _static_##func) \
void _static_##func()
REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
} \
} \
- [[accumulate]] void stats_get() \
+ ACCUMULATE void stats_get() \
{ \
T it = getstat_##T(STAT_##id.m_id); \
/* if (it != CAT(_STAT(id), _prev)) \
REGISTRY_RESERVE(Stats, m_id, STAT_##id, z); \
} \
} \
- [[accumulate]] void stats_add() \
+ ACCUMULATE void stats_add() \
{ \
.T fld = _STAT(id); \
addstat_##T(STAT_##id.m_id, fld); \
/** TODO: do we want the global copy to update? */
#define REGISTER_STAT_3(id, T, expr) \
REGISTER_STAT_2(id, T); \
- [[accumulate]] void GlobalStats_update(entity this) { STAT(id, this) = (expr); } \
+ ACCUMULATE void GlobalStats_update(entity this) { STAT(id, this) = (expr); } \
STATIC_INIT(worldstat_##id) { entity this = STATS; STAT(id, this) = (expr); }
#else
#define REGISTER_STAT_2(id, type)
#include "sort.qh"
#include "oo.qh"
+// string logic
+//
+// true: is truthy
+// == "": is equal to ""
+// is "": has the same string index as the string constant ""
+// strunzone: can be strunzoned
+//
+// | | true | == "" | is "" | strunzone |
+// | :----------: | :--: | :---: | :---: | :-------: |
+// | nil | | yes | | |
+// | strcat(nil) | yes | yes | | |
+// | strzone(nil) | yes | yes | | yes |
+// | "" | yes | yes | yes | |
+// | strcat("") | yes | yes | | |
+// | strzone("") | yes | yes | | yes |
+// | "s" | yes | | | |
+// | strcat("s") | yes | | | |
+// | strzone("s") | yes | | | yes |
+
#ifdef CSQC
float stringwidth_colors(string s, vector theSize)
{
}
#endif
+#define strcpy(this, s) MACRO_BEGIN \
+ if (this) { \
+ strunzone(this); \
+ } \
+ this = strzone(s); \
+MACRO_END
+
+#define strfree(this) MACRO_BEGIN \
+ if (this) { \
+ strunzone(this); \
+ } \
+ this = string_null; \
+MACRO_END
+
ERASEABLE
string seconds_tostring(float sec)
{
/** Use UpperCamelCase for suite and test only */
#define TEST(suite, test) \
void _TEST_##suite##_##test(); \
- [[accumulate]] int TEST_RunAll_accumulated(int f) { \
+ ACCUMULATE int TEST_RunAll_accumulated(int f) { \
if (!TEST_Run(#suite "_" #test)) ++f; \
return = f; \
} \
{
LOG_INFO("url_URI_Get_Callback: out of memory in buf_create");
e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return 1;
}
{
LOG_INFO("url_URI_Get_Callback: out of memory in buf_create");
e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return 1;
}
{
// an ERROR
e.url_ready(e, e.url_ready_pass, -fabs(status));
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return 1;
}
{
LOG_INFO("url_single_fopen: out of memory in buf_create");
rdy(e, pass, URL_READY_ERROR);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return;
}
LOG_INFO("url_fclose: too many concurrent requests");
e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
buf_del(e.url_wbuf);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return;
}
LOG_INFO("url_fclose: failure in crypto_uri_postbuf");
e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
buf_del(e.url_wbuf);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
return;
}
// we have READ all data, just close
e.url_ready(e, e.url_ready_pass, URL_READY_CLOSED);
buf_del(e.url_rbuf);
- strunzone(e.url_url);
+ strfree(e.url_url);
delete(e);
}
}
{
LOG_INFO("uri_multi_ready: got HTTP error 422, data is in unusable format - not continuing");
me.url_ready(fh, me.url_ready_pass, status);
- strunzone(me.url_url);
+ strfree(me.url_url);
delete(me);
return;
}
if (n <= me.url_attempt)
{
me.url_ready(fh, me.url_ready_pass, status);
- strunzone(me.url_url);
+ strfree(me.url_url);
delete(me);
return;
}
float exp(float e)
{
- return (M_E ** e);
+ return pow(M_E, e);
}
float exp2(float e)
{
- return (2 ** e);
+ return pow(2, e);
}
float expm1(float e)
{
vector v;
v.z = 0;
v.y = ilogb(e) + 1;
- v.x = e / (2 ** v.y);
+ v.x = e / pow(2, v.y);
return v;
}
int ilogb(float e)
{
return floor(log2(fabs(e)));
}
-float ldexp(float e, int e)
+float ldexp(float x, int e)
{
- return e * (2 ** e);
+ return x * pow(2, e);
}
float logn(float e, float base)
{
float scalbn(float e, int n)
{
- return e * (2 ** n);
+ return e * pow(2, n);
}
float cbrt(float e)
{
- return copysign((fabs(e) ** (1.0/3.0)), e);
+ return copysign(pow(fabs(e), (1.0/3.0)), e);
}
float hypot(float e, float f)
{
void InputBox_setText(entity me, string txt)
{
- if (me.text) strunzone(me.text);
+ strfree(me.text);
SUPER(InputBox).setText(me, strzone(txt));
}
me.text = txt;
if (txt != me.currentText)
{
- if (me.currentText) strunzone(me.currentText);
- me.currentText = strzone(txt);
+ strcpy(me.currentText, txt);
me.recalcPos = 1;
}
}
t = me.textEntity.toString(me.textEntity);
if (t != me.currentText)
{
- if (me.currentText) strunzone(me.currentText);
- me.currentText = strzone(t);
+ strcpy(me.currentText, t);
me.recalcPos = 1;
}
}
if (m_goto_buffer)
{
m_goto(m_goto_buffer);
- strunzone(m_goto_buffer);
- m_goto_buffer = string_null;
+ strfree(m_goto_buffer);
}
if (Menu_Active) m_display(); // delayed menu display
{
// fade out if tooltip of a certain item has changed
menuTooltipState = 3;
- if (prev_tooltip) strunzone(prev_tooltip);
- prev_tooltip = strzone(it.tooltip);
+ strcpy(prev_tooltip, it.tooltip);
}
else if (menuTooltipItem && !m_testmousetooltipbox(pos))
{
menuTooltipOrigin.x = -1; // unallocated
- if (menuTooltipText) strunzone(menuTooltipText);
- menuTooltipText = strzone(gettooltip());
+ strcpy(menuTooltipText, gettooltip());
int i = 0;
float w = 0;
if (menuTooltipItem == NULL)
{
- if (menuTooltipText)
- {
- strunzone(menuTooltipText);
- menuTooltipText = string_null;
- }
+ strfree(menuTooltipText);
return;
}
else
{
if (!menuInitialized)
{
- if (m_goto_buffer) strunzone(m_goto_buffer);
- m_goto_buffer = strzone(itemname);
+ strcpy(m_goto_buffer, itemname);
return;
}
if (itemname == "") // this can be called by GameCommand
#include <common/mutators/base.qh>
// register all possible hooks here
-
+
// to use a hook, first register your mutator using REGISTER_MUTATOR
// then create your function using MUTATOR_HOOKFUNCTION
for(i = 0; i < campaign_entries; ++i)
{
l = l0;
- if(campaign_longdesc_wrapped[i])
- strunzone(campaign_longdesc_wrapped[i]);
+ strfree(campaign_longdesc_wrapped[i]);
n = tokenizebyseparator(campaign_longdesc[i], "\n");
r = "";
for(j = 0; j < n; ++j)
void XonoticCampaignList_loadCvars(entity me)
{
// read campaign cvars
- if(campaign_name)
- strunzone(campaign_name);
- if(me.cvarName)
- strunzone(me.cvarName);
- campaign_name = strzone(cvar_string("g_campaign_name"));
- me.cvarName = strzone(strcat("g_campaign", campaign_name, "_index"));
+ strcpy(campaign_name, cvar_string("g_campaign_name"));
+ strcpy(me.cvarName, strcat("g_campaign", campaign_name, "_index"));
registercvar(me.cvarName, "", 0); // saved by server QC anyway
CampaignFile_Unload();
CampaignFile_Load(0, CAMPAIGN_MAX_ENTRIES);
float a;
rgb = stov(cvar_string("crosshair_color"));
a = cvar("crosshair_alpha");
- if(me.src)
- strunzone(me.src);
- me.src = strzone(strcat("/gfx/crosshair", cvar_string("crosshair")));
+ strcpy(me.src, strcat("/gfx/crosshair", cvar_string("crosshair")));
sz = draw_PictureSize(me.src);
sz = globalToBoxSize(sz, me.size);
if(me.nItems == 0)
return;
- if(me.cvarName)
- strunzone(me.cvarName);
- if(me.cvarDescription)
- strunzone(me.cvarDescription);
- if(me.cvarType)
- strunzone(me.cvarType);
- if(me.cvarDefault)
- strunzone(me.cvarDefault);
- me.cvarName = strzone(bufstr_get(me.handle, me.selectedItem));
- me.cvarDescription = strzone(cvar_description(me.cvarName));
- me.cvarDefault = strzone(cvar_defstring(me.cvarName));
+ strfree(me.cvarType);
+ strcpy(me.cvarName, bufstr_get(me.handle, me.selectedItem));
+ strcpy(me.cvarDescription, cvar_description(me.cvarName));
+ strcpy(me.cvarDefault, cvar_defstring(me.cvarName));
me.cvarNameBox.setText(me.cvarNameBox, me.cvarName);
me.cvarDescriptionBox.setText(me.cvarDescriptionBox, me.cvarDescription);
float needsForcing = me.updateCvarType(me);
void DemoList_Filter_Change(entity box, entity me)
{
- if(me.filterString)
- strunzone(me.filterString);
+ strfree(me.filterString);
if(box.text != "")
{
// clear old values
for(i = 0; i < e.nValues; ++i);
{
- if(e.(valueStrings[i]))
- {
- strunzone(e.(valueStrings[i]));
- e.(valueStrings[i]) = string_null;
- }
- if(e.(valueIdentifiers[i]))
- {
- strunzone(e.(valueIdentifiers[i]));
- e.(valueIdentifiers[i]) = string_null;
- }
+ strfree(e.(valueStrings[i]));
+ strfree(e.(valueIdentifiers[i]));
}
e.clearValues(e);
me.startButton.onClickEntity = mlb;
MapInfo_Get_ByID(i);
- if(me.currentMapBSPName)
- {
- strunzone(me.currentMapBSPName);
- strunzone(me.currentMapTitle);
- strunzone(me.currentMapAuthor);
- strunzone(me.currentMapDescription);
- strunzone(me.currentMapPreviewImage);
- }
- me.currentMapBSPName = strzone(MapInfo_Map_bspname);
- me.currentMapTitle = strzone(strdecolorize(MapInfo_Map_title));
- me.currentMapAuthor = strzone(strdecolorize(MapInfo_Map_author));
- me.currentMapDescription = strzone(MapInfo_Map_description);
- me.currentMapPreviewImage = strzone(strcat("/maps/", MapInfo_Map_bspname));
+ strcpy(me.currentMapBSPName, MapInfo_Map_bspname);
+ strcpy(me.currentMapTitle, strdecolorize(MapInfo_Map_title));
+ strcpy(me.currentMapAuthor, strdecolorize(MapInfo_Map_author));
+ strcpy(me.currentMapDescription, MapInfo_Map_description);
+ strcpy(me.currentMapPreviewImage, strcat("/maps/", MapInfo_Map_bspname));
me.frame.setText(me.frame, me.currentMapBSPName);
me.titleLabel.setText(me.titleLabel, me.currentMapTitle);
return _("Most Weapons Arena");
if(s == weaponarenastring_cvar)
return weaponarenastring;
- if(weaponarenastring)
- strunzone(weaponarenastring);
- if(weaponarenastring_cvar)
- strunzone(weaponarenastring_cvar);
- weaponarenastring_cvar = strzone(s);
+ strcpy(weaponarenastring_cvar, s);
n = tokenize_console(s);
s = "";
}
s = sprintf(_("%s Arena"), s);
- weaponarenastring = strzone(s);
+ strcpy(weaponarenastring, s);
return weaponarenastring;
}
// ====================================
// First clear and unzone the strings
// ====================================
- if(me.currentServerName)
- strunzone(me.currentServerName);
- me.currentServerName = string_null;
-
- if(me.currentServerCName)
- strunzone(me.currentServerCName);
- me.currentServerCName = string_null;
-
- if(me.currentServerType)
- strunzone(me.currentServerType);
- me.currentServerType = string_null;
-
- if(me.currentServerMap)
- strunzone(me.currentServerMap);
- me.currentServerMap = string_null;
-
- if(me.currentServerPlayers)
- strunzone(me.currentServerPlayers);
- me.currentServerPlayers = string_null;
-
- if(me.currentServerNumPlayers)
- strunzone(me.currentServerNumPlayers);
- me.currentServerNumPlayers = string_null;
-
- if(me.currentServerNumBots)
- strunzone(me.currentServerNumBots);
- me.currentServerNumBots = string_null;
-
- if(me.currentServerNumFreeSlots)
- strunzone(me.currentServerNumFreeSlots);
- me.currentServerNumFreeSlots = string_null;
-
- if(me.currentServerMod)
- strunzone(me.currentServerMod);
- me.currentServerMod = string_null;
-
- if(me.currentServerVersion)
- strunzone(me.currentServerVersion);
- me.currentServerVersion = string_null;
-
+ strfree(me.currentServerName);
+ strfree(me.currentServerCName);
+ strfree(me.currentServerType);
+ strfree(me.currentServerMap);
+ strfree(me.currentServerPlayers);
+ strfree(me.currentServerNumPlayers);
+ strfree(me.currentServerNumBots);
+ strfree(me.currentServerNumFreeSlots);
+ strfree(me.currentServerMod);
+ strfree(me.currentServerVersion);
// not zoned!
- //if(me.currentServerEncrypt)
- // strunzone(me.currentServerEncrypt);
- //me.currentServerEncrypt = string_null;
- if(me.currentServerPure)
- strunzone(me.currentServerPure);
- me.currentServerPure = string_null;
-
- if(me.currentServerKey)
- strunzone(me.currentServerKey);
- me.currentServerKey = string_null;
-
- if(me.currentServerID)
- strunzone(me.currentServerID);
- me.currentServerID = string_null;
+ // strfree(me.currentServerEncrypt);
+ strfree(me.currentServerPure);
+ strfree(me.currentServerKey);
+ strfree(me.currentServerID);
// ==========================
// Now, fill in the strings
{
if (me.currentScrPath == scrImage)
return;
- if (me.currentScrPath)
- strunzone(me.currentScrPath);
- me.currentScrPath = strzone(scrImage);
+ strcpy(me.currentScrPath, scrImage);
me.screenshotImage.load(me.screenshotImage, me.currentScrPath);
}
void XonoticScreenshotBrowserTab_fill(entity me)
if (me.currentScrPath == scrImage)
return;
- if (me.currentScrPath)
- strunzone(me.currentScrPath);
- me.currentScrPath = strzone(scrImage);
+ strcpy(me.currentScrPath, scrImage);
me.screenshotImage.load(me.screenshotImage, me.currentScrPath);
me.frame.setText(me.frame, me.screenshotImage.screenshotTitle);
}
void HUDSkinList_SavedName_Change(entity box, entity me)
{
- if(me.savedName)
- strunzone(me.savedName);
+ strfree(me.savedName);
if(box.text != "")
me.savedName = strzone(box.text);
- else
- me.savedName = string_null;
}
void HUDSkinList_Filter_Change(entity box, entity me)
{
- if(me.filterString)
- strunzone(me.filterString);
+ strfree(me.filterString);
if(box.text != "")
{
else
me.filterString = strzone(strcat("*", box.text, "*"));
}
- else
- me.filterString = string_null;
me.getHUDSkins(me);
}
for(int i = 0; i < MAX_KEYBINDS; ++i)
{
- if(Xonotic_KeyBinds_Functions[i])
- strunzone(Xonotic_KeyBinds_Functions[i]);
- Xonotic_KeyBinds_Functions[i] = string_null;
- if(Xonotic_KeyBinds_Descriptions[i])
- strunzone(Xonotic_KeyBinds_Descriptions[i]);
- Xonotic_KeyBinds_Descriptions[i] = string_null;
+ strfree(Xonotic_KeyBinds_Functions[i]);
+ strfree(Xonotic_KeyBinds_Descriptions[i]);
}
Xonotic_KeyBinds_Count = 0;
}
for(i = 0; i < MapInfo_count; ++i)
draw_PreloadPicture(strcat("/maps/", MapInfo_BSPName_ByID(i)));
- if(me.g_maplistCache)
- strunzone(me.g_maplistCache);
s = "0";
for(i = 1; i < MapInfo_count; i *= 2)
s = strcat(s, s);
);
}
}
- me.g_maplistCache = strzone(s);
+ strcpy(me.g_maplistCache, s);
if(gt != me.lastGametype || f != me.lastFeatures)
{
me.lastGametype = gt;
void MapList_StringFilterBox_Change(entity box, entity me)
{
- if(me.stringFilter)
- strunzone(me.stringFilter);
+ strfree(me.stringFilter);
if(box.text != "")
me.stringFilter = strzone(box.text);
- else
- me.stringFilter = string_null;
me.refilter(me);
}
if(time < me.typeToSearchTime)
{
save = substring(me.typeToSearchString, 0, strlen(me.typeToSearchString) - 1);
- if(me.typeToSearchString)
- strunzone(me.typeToSearchString);
- me.typeToSearchString = strzone(save);
+ strcpy(me.typeToSearchString, save);
me.typeToSearchTime = time + 0.5;
if(strlen(me.typeToSearchString))
{
save = ch;
else
save = strcat(me.typeToSearchString, ch);
- if(me.typeToSearchString)
- strunzone(me.typeToSearchString);
- me.typeToSearchString = strzone(save);
+ strcpy(me.typeToSearchString, save);
me.typeToSearchTime = time + 0.5;
MapInfo_FindName(me.typeToSearchString);
if(MapInfo_FindName_firstResult >= 0)
{
me.idxModels = mod(me.idxModels + d + me.numModels, me.numModels);
- if(me.currentModel)
- strunzone(me.currentModel);
- if(me.currentModelTitle)
- strunzone(me.currentModelTitle);
- if(me.currentModelImage)
- strunzone(me.currentModelImage);
- if(me.currentModelDescription)
- strunzone(me.currentModelDescription);
-
// select model #i!
- me.currentModelTitle = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_TITLE));
- me.currentModelImage = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_IMAGE));
+ strcpy(me.currentModelTitle, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_TITLE));
+ strcpy(me.currentModelImage, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_IMAGE));
me.currentSkin = stof(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_SKIN));
- me.currentModel = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_MODEL));
- me.currentModelDescription = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC));
+ strcpy(me.currentModel, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_MODEL));
+ strcpy(me.currentModelDescription, bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC));
// fix the image
if(draw_PictureSize(me.currentModelImage) == '0 0 0')
{
me.screenshotTime = time;
me.src = theImage;
- if (me.screenshotTitle)
- strunzone(me.screenshotTitle);
- me.screenshotTitle = strzone(substring(me.src, 13, strlen(theImage) - 13)); //strip "/screenshots/"
+ strcpy(me.screenshotTitle, substring(me.src, 13, strlen(theImage) - 13)); //strip "/screenshots/"
me.initZoom(me); // this image may have a different size
me.setZoom(me, 0, 0);
void ScreenshotList_Filter_Change(entity box, entity me)
{
- if(me.filterString)
- strunzone(me.filterString);
+ strfree(me.filterString);
if(box.text != "")
{
else
me.filterString = strzone(strcat("*", box.text, "*"));
}
- else
- me.filterString = string_null;
ScreenshotList_Refresh_Click(NULL, me);
}
} } \
if(catnum) \
{ \
- strunzone(categories[i].override_string); \
- categories[i].override_string = string_null; \
+ strfree(categories[i].override_string); \
categories[i].override_field = catnum; \
continue; \
} \
); \
} \
} \
- strunzone(categories[i].override_string); \
- categories[i].override_string = string_null; \
+ strfree(categories[i].override_string); \
categories[i].override_field = 0; \
}
PROCESS_OVERRIDE(cat_enoverride_string, cat_enoverride)
if(gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT) != me.nItems)
return; // sorry, it would be wrong
- if(me.selectedServer)
- strunzone(me.selectedServer);
- me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
+ strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
me.ipAddressBox.setText(me.ipAddressBox, me.selectedServer);
me.ipAddressBox.cursorPos = strlen(me.selectedServer);
}
else { me.nItems = gethostcachevalue(SLIST_HOSTCACHEVIEWCOUNT); }
- me.connectButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
- me.infoButton.disabled = ((me.nItems == 0) || !owned);
- me.favoriteButton.disabled = ((me.nItems == 0) && (me.ipAddressBox.text == ""));
+ me.connectButton.disabled = (me.lockedSelectedItem || (me.nItems == 0 && me.ipAddressBox.text == ""));
+ me.infoButton.disabled = (me.lockedSelectedItem || me.nItems == 0 || !owned);
+ me.favoriteButton.disabled = (me.lockedSelectedItem || (me.nItems == 0 && me.ipAddressBox.text == ""));
if(me.lockedSelectedItem)
{
{
if(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem) != me.selectedServer)
{
- if(me.selectedServer)
- strunzone(me.selectedServer);
- me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
+ strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
}
found = true;
}
// selected server disappeared, select the last server (scrolling to it)
if(me.selectedItem >= me.nItems)
SUPER(XonoticServerList).setSelected(me, me.nItems - 1);
- if(me.selectedServer)
- strunzone(me.selectedServer);
- me.selectedServer = strzone(gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
+ strcpy(me.selectedServer, gethostcachestring(SLIST_FIELD_CNAME, me.selectedItem));
}
}
}
void ServerList_Filter_Change(entity box, entity me)
{
- if(me.filterString)
- strunzone(me.filterString);
+ strfree(me.filterString);
if(box.text != "")
me.filterString = strzone(box.text);
- else
- me.filterString = string_null;
me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
me.ipAddressBox.setText(me.ipAddressBox, "");
me.sortButton4.forcePressed = 0;
me.sortButton5.forcePressed = (fld == SLIST_FIELD_NUMHUMANS);
me.selectedItem = 0;
- if(me.selectedServer)
- strunzone(me.selectedServer);
- me.selectedServer = string_null;
+ strfree(me.selectedServer);
me.refreshServerList(me, REFRESHSERVERLIST_REFILTER);
}
void XonoticServerList_positionSortButton(entity me, entity btn, float theOrigin, float theSize, string theTitle, void(entity, entity) theFunc)
}
void ServerList_Connect_Click(entity btn, entity me)
{
- localcmd(sprintf("connect %s\n",
- ((me.ipAddressBox.text != "") ?
- me.ipAddressBox.text : me.selectedServer
- )
- ));
+ if (me.lockedSelectedItem)
+ return;
+ string sv = (me.ipAddressBox.text != "") ? me.ipAddressBox.text : me.selectedServer;
+ localcmd(sprintf("connect %s\n", sv));
}
void ServerList_Favorite_Click(entity btn, entity this)
{
}
}
- if(isSelected)
+ if(isSelected && !me.lockedSelectedItem)
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
else if(isFocused)
{
ATTRIB(XonoticServerList, columnTypeSize, float, 0);
ATTRIB(XonoticServerList, columnPlayersOrigin, float, 0);
ATTRIB(XonoticServerList, columnPlayersSize, float, 0);
- ATTRIB(XonoticServerList, lockedSelectedItem, bool, true); // initially keep selected the first item of the list, avoiding an unwanted scrolling
+ ATTRIB(XonoticServerList, lockedSelectedItem, bool, true); // initially keep selected the first item of the list to avoid unwanted scrolling
ATTRIB(XonoticServerList, selectedServer, string); // to restore selected server when needed
METHOD(XonoticServerList, setSelected, void(entity, float));
void SoundList_Filter_Change(entity box, entity me)
{
- if(me.filterString)
- strunzone(me.filterString);
+ strfree(me.filterString);
if(box.text != "")
me.filterString = strzone(box.text);
- else
- me.filterString = string_null;
me.getSounds(me);
}
theTooltip = string_null;
}
- if(e.tooltip)
- strunzone(e.tooltip);
+ strfree(e.tooltip);
e.tooltip = (theTooltip != "") ? strzone(theTooltip) : string_null;
}
}
else
{
- strunzone(campaign_name_previous);
- campaign_name_previous = strzone(campaign_name);
+ strcpy(campaign_name_previous, campaign_name);
campaign_won_previous = cvar(strcat("g_campaign", campaign_name, "_won"));
}
}
}
void XonoticWeaponarenaCheckBox_loadCvars(entity me)
{
- float n = tokenize_console(cvar_string("menu_weaponarena"));
- float i;
- for(i=0; i<n; ++i)
+ int n = tokenize_console(cvar_string("menu_weaponarena"));
+ for (int i = 0; i < n; i++)
{
if(argv(i) == me.netname)
{
float autocvar_g_maxplayers_spectator_blocktime;
float autocvar_g_maxpushtime;
float autocvar_g_maxspeed;
-bool autocvar_g_instagib;
+#define autocvar_g_instagib cvar("g_instagib")
#define autocvar_g_mirrordamage cvar("g_mirrordamage")
#define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
bool autocvar_g_mirrordamage_onlyweapons;
bool autocvar_g_use_ammunition;
bool autocvar_g_waypointeditor;
bool autocvar_g_waypointeditor_symmetrical;
+bool autocvar_g_waypointeditor_symmetrical_allowload = true;
vector autocvar_g_waypointeditor_symmetrical_origin;
int autocvar_g_waypointeditor_symmetrical_order;
vector autocvar_g_waypointeditor_symmetrical_axis;
if (!IS_BOT_CLIENT(this))
return;
bot_clearqueue(this);
- if(this.cleanname)
- strunzone(this.cleanname);
- if(this.netname_freeme)
- strunzone(this.netname_freeme);
- if(this.playermodel_freeme)
- strunzone(this.playermodel_freeme);
- if(this.playerskin_freeme)
- strunzone(this.playerskin_freeme);
- this.cleanname = string_null;
- this.netname_freeme = string_null;
- this.playermodel_freeme = string_null;
- this.playerskin_freeme = string_null;
+ strfree(this.cleanname);
+ strfree(this.netname_freeme);
+ strfree(this.playermodel_freeme);
+ strfree(this.playerskin_freeme);
if(this.bot_cmd_current)
delete(this.bot_cmd_current);
if(bot_waypoint_queue_owner == this)
bot_cmd.bot_cmd_parm_float = stof(parm);
break;
case BOT_CMD_PARAMETER_STRING:
- if(bot_cmd.bot_cmd_parm_string)
- strunzone(bot_cmd.bot_cmd_parm_string);
- bot_cmd.bot_cmd_parm_string = strzone(parm);
+ strcpy(bot_cmd.bot_cmd_parm_string, parm);
break;
case BOT_CMD_PARAMETER_VECTOR:
if(substring(parm, 0, 1) != "\'")
it.bot_barrier = 0;
for(int i = 0; i < it.bot_places_count; ++i)
{
- strunzone(it.(bot_placenames[i]));
- it.(bot_placenames[i]) = string_null;
+ strfree(it.(bot_placenames[i]));
}
it.bot_places_count = 0;
});
return;
}
- // add 3 comments to not break compatibility with older Xonotic versions
+ float sym = autocvar_g_waypointeditor_symmetrical;
+ string sym_str = ftos(sym);
+ if (sym == -1 || (sym == 1 && autocvar_g_waypointeditor_symmetrical_order >= 2))
+ {
+ if (sym == 1)
+ {
+ sym_str = cons(sym_str, "-");
+ sym_str = cons(sym_str, "-");
+ }
+ else
+ {
+ sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.x));
+ sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.y));
+ }
+ if (autocvar_g_waypointeditor_symmetrical_order >= 2)
+ sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_order));
+ }
+ else if (autocvar_g_waypointeditor_symmetrical == -2)
+ {
+ sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.x));
+ sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.y));
+ }
+
+ // a group of 3 comments doesn't break compatibility with older Xonotic versions
// (they are read as a waypoint with origin '0 0 0' and flag 0 though)
fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
- fputs(file, strcat("//", "\n"));
+ fputs(file, strcat("//", "WAYPOINT_SYMMETRY ", sym_str, "\n"));
fputs(file, strcat("//", "\n"));
int c = 0;
bool parse_comments = true;
float ver = 0;
+ float sym = 0;
+ float sym_param1 = 0, sym_param2 = 0, sym_param3 = 0;
while ((s = fgets(file)))
{
{
if(substring(s, 2, 17) == "WAYPOINT_VERSION ")
ver = stof(substring(s, 19, -1));
+ else if(substring(s, 2, 18) == "WAYPOINT_SYMMETRY ")
+ {
+ int tokens = tokenizebyseparator(substring(s, 20, -1), " ");
+ if (tokens) { sym = stof(argv(0)); }
+ if (tokens > 1) { sym_param1 = stof(argv(1)); }
+ if (tokens > 2) { sym_param2 = stof(argv(2)); }
+ if (tokens > 3) { sym_param3 = stof(argv(3)); }
+ }
continue;
}
else
fclose(file);
LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints");
+ if (autocvar_g_waypointeditor && autocvar_g_waypointeditor_symmetrical_allowload)
+ {
+ cvar_set("g_waypointeditor_symmetrical", ftos(sym));
+ if (sym == 1 && sym_param3 < 2)
+ cvar_set("g_waypointeditor_symmetrical_order", "0"); // make sure this is reset if not loaded
+ if (sym == -1 || (sym == 1 && sym_param3 >= 2))
+ {
+ string params;
+ if (sym == 1)
+ params = cons("-", "-");
+ else
+ {
+ params = cons(ftos(sym_param1), ftos(sym_param2));
+ cvar_set("g_waypointeditor_symmetrical_origin", params);
+ }
+ cvar_set("g_waypointeditor_symmetrical_order", ftos(sym_param3));
+ LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
+ }
+ else if (sym == -2)
+ {
+ string params = strcat(ftos(sym_param1), " ", ftos(sym_param2));
+ cvar_set("g_waypointeditor_symmetrical_axis", params);
+ LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with axis ", params);
+ }
+ else
+ LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym));
+ LOG_INFO(strcat("g_waypointeditor_symmetrical", " has been set to ", cvar_string("g_waypointeditor_symmetrical")));
+ }
+
return cwp + cwb;
}
// increase by 0.01 when changes require only waypoint relinking
// increase by 1 when changes require to manually edit waypoints
// max 2 decimal places, always specified
-#define WAYPOINT_VERSION 1.00
+#define WAYPOINT_VERSION 1.01
// fields you can query using prvm_global server to get some statistics about waypoint linking culling
float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled;
{
if(cvar_string_campaignwrapper(theCvar) == theValue)
return;
- string s;
- s = cvar_campaignwrapper_list;
+ string s = cvar_campaignwrapper_list;
cvar_campaignwrapper_list = strzone(strcat("; ", theCvar, " ", theValue, s));
strunzone(s);
//print(cvar_campaignwrapper_list, "\n");
MUTATOR_CALLHOOK(ClientDisconnect, this);
- if (CS(this).netname_previous) strunzone(CS(this).netname_previous); // needs to be before the CS entity is removed!
- if (CS(this).weaponorder_byimpulse) strunzone(CS(this).weaponorder_byimpulse);
+ strfree(CS(this).netname_previous); // needs to be before the CS entity is removed!
+ strfree(CS(this).weaponorder_byimpulse);
ClientState_detach(this);
Portal_ClearAll(this);
bot_relinkplayerlist();
- if (this.clientstatus) strunzone(this.clientstatus);
+ strfree(this.clientstatus);
if (this.personal) delete(this.personal);
this.playerid = 0;
Fire_ApplyDamage(this);
Fire_ApplyEffect(this);
- if (!g_instagib)
+ if (!autocvar_g_instagib)
{
if (this.items & ITEM_Strength.m_itemid)
{
return false;
}
- bool have_hook = false;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(this.(weaponentity).hook.state)
- {
- have_hook = true;
- break;
- }
- }
- bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
- if (have_hook) {
- do_crouch = false;
- //} else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
- //do_crouch = false;
- } else if (this.vehicle) {
- do_crouch = false;
- } else if (STAT(FROZEN, this)) {
- do_crouch = false;
- }
-
- if (do_crouch) {
- if (!this.crouch) {
- this.crouch = true;
- this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
- setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
- // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
- }
- } else if (this.crouch) {
- tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
- if (!trace_startsolid) {
- this.crouch = false;
- this.view_ofs = STAT(PL_VIEW_OFS, this);
- setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
- }
- }
-
FixPlayermodel(this);
if (this.shootfromfixedorigin != autocvar_g_shootfromfixedorigin) {
}
if (!assume_unchanged && autocvar_sv_eventlog)
GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this, false)));
- if (CS(this).netname_previous) strunzone(CS(this).netname_previous);
- CS(this).netname_previous = strzone(this.netname);
+ strcpy(CS(this).netname_previous, this.netname);
}
// version nagging
bool Spectate(entity this, entity pl);
-#define SPECTATE_COPY() [[accumulate]] void SpectateCopy(entity this, entity spectatee)
+#define SPECTATE_COPY() ACCUMULATE void SpectateCopy(entity this, entity spectatee)
#define SPECTATE_COPYFIELD(fld) SPECTATE_COPY() { this.(fld) = spectatee.(fld); }
sprint(caller, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
return;
}
- if (argc >= 3) VoiceMessage(caller, e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
- else VoiceMessage(caller, e, "");
+ string msg = "";
+ if (argc >= 3)
+ msg = substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2));
+ VoiceMessage(caller, e, msg);
return;
}
break;
});
- if (!found && arg_lower != "random") { print_to(caller, "Invalid monster"); return; }
+ if (!found && arg_lower != "random" && arg_lower != "anyrandom") { print_to(caller, "Invalid monster"); return; }
totalspawned += 1;
WarpZone_TraceBox(CENTER_OR_VIEWOFS(caller), caller.mins, caller.maxs, CENTER_OR_VIEWOFS(caller) + v_forward * 150, true, caller);
if (vote_called)
{
- strunzone(vote_called_command);
- strunzone(vote_called_display);
- strunzone(vote_caller_name);
+ strfree(vote_called_command);
+ strfree(vote_called_display);
+ strfree(vote_caller_name);
}
vote_called = VOTE_NULL;
vote_caller = NULL;
- vote_caller_name = string_null;
vote_endtime = 0;
- vote_called_command = string_null;
- vote_called_display = string_null;
-
vote_parsed_command = string_null;
vote_parsed_display = string_null;
if (!VoteCommand_checkargs(startpos, argc)) return 0;
+ switch (MUTATOR_CALLHOOK(VoteCommand_Parse, caller, first_command, vote_command, startpos, argc))
+ {
+ case MUT_VOTEPARSE_CONTINUE: { break; }
+ case MUT_VOTEPARSE_SUCCESS: { return 1; }
+ case MUT_VOTEPARSE_INVALID: { return -1; }
+ case MUT_VOTEPARSE_UNACCEPTABLE: { return 0; }
+ }
+
switch (first_command) // now go through and parse the proper commands to adjust as needed.
{
case "kick":
// Globals
-float g_footsteps, g_grappling_hook, g_instagib;
+float g_footsteps, g_grappling_hook;
float g_warmup_allguns;
float g_warmup_allow_timeout;
float warmup_stage;
}
}
- if(!g_instagib)
+ if(!autocvar_g_instagib)
{
// apply strength multiplier
if (attacker.items & ITEM_Strength.m_itemid)
#include "../common/triggers/triggers.qh"
entityclass(BGMScript);
-class(BGMScript) .string bgmscript;
-class(BGMScript) .float bgmscriptattack;
-class(BGMScript) .float bgmscriptdecay;
-class(BGMScript) .float bgmscriptsustain;
-class(BGMScript) .float bgmscriptrelease;
+classfield(BGMScript) .string bgmscript;
+classfield(BGMScript) .float bgmscriptattack;
+classfield(BGMScript) .float bgmscriptdecay;
+classfield(BGMScript) .float bgmscriptsustain;
+classfield(BGMScript) .float bgmscriptrelease;
#include "../common/constants.qh"
#include "../lib/csqcmodel/sv_model.qh"
string k, v, d;
float n, i, adding, pureadding;
- if(cvar_changes)
- strunzone(cvar_changes);
- cvar_changes = string_null;
- if(cvar_purechanges)
- strunzone(cvar_purechanges);
- cvar_purechanges = string_null;
+ strfree(cvar_changes);
+ strfree(cvar_purechanges);
cvar_purechanges_count = 0;
h = buf_create();
error("empty maplist, cannot select a new map");
Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
- if(Map_Current_Name)
- strunzone(Map_Current_Name);
- Map_Current_Name = strzone(argv(Map_Current)); // will be automatically freed on exit thanks to DP
+ strcpy(Map_Current_Name, argv(Map_Current)); // will be automatically freed on exit thanks to DP
// this may or may not be correct, but who cares, in the worst case a map
// isn't chosen in the first pass that should have been
}
if(argc == 0)
goto killme;
- if(OnlineBanList_Servers)
- strunzone(OnlineBanList_Servers);
- OnlineBanList_Servers = argv(0);
- for(i = 1; i < argc; ++i)
- OnlineBanList_Servers = strcat(OnlineBanList_Servers, ";", argv(i));
- OnlineBanList_Servers = strzone(OnlineBanList_Servers);
+ string s = argv(0); for(i = 1; i < argc; ++i) s = strcat(s, ";", argv(i));
+ strcpy(OnlineBanList_Servers, s);
uri = strcat( "action=list&hostname=", uri_escape(autocvar_hostname));
uri = strcat(uri, "&servers=", uri_escape(OnlineBanList_Servers));
{
for(int j = 0; j < mapvote_count; ++j)
{
- if ( mapvote_maps[j] )
- {
- strunzone(mapvote_maps[j]);
- mapvote_maps[j] = string_null;
- }
- if ( mapvote_maps_pakfile[j] )
- {
- strunzone(mapvote_maps_pakfile[j]);
- mapvote_maps_pakfile[j] = string_null;
- }
+ strfree(mapvote_maps[j]);
+ strfree(mapvote_maps_pakfile[j]);
}
}
{
if (f < 0)
{
- if (store.(field))
- strunzone(store.(field));
- store.(field) = string_null;
+ strfree(store.(field));
}
else if (f > 0)
{
if (thisname == name)
{
- if (store.(field))
- strunzone(store.(field));
- store.(field) = strzone(argv(f + 1));
+ strcpy(store.(field), argv(f + 1));
}
}
else
string s = func(this, strcat1(store.(field)));
if (s != store.(field))
{
- strunzone(store.(field));
- store.(field) = strzone(s);
+ strcpy(store.(field), s);
}
}
}
}
string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(entity this, string wo)
{
- string o;
- o = W_FixWeaponOrder_ForceComplete(wo);
- if(CS(this).weaponorder_byimpulse)
- {
- strunzone(CS(this).weaponorder_byimpulse);
- CS(this).weaponorder_byimpulse = string_null;
- }
- CS(this).weaponorder_byimpulse = strzone(W_FixWeaponOrder_BuildImpulseList(o));
+ string o = W_FixWeaponOrder_ForceComplete(wo);
+ strcpy(CS(this).weaponorder_byimpulse, W_FixWeaponOrder_BuildImpulseList(o));
return o;
}
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
- g_instagib = cvar("g_instagib");
-
sv_clones = cvar("sv_clones");
sv_foginterval = cvar("sv_foginterval");
g_footsteps = cvar("g_footsteps");
#include <common/mutators/base.qh>
// register all possible hooks here
-
+
// to use a hook, first register your mutator using REGISTER_MUTATOR
// then create your function using MUTATOR_HOOKFUNCTION
#define EV_W_DecreaseAmmo(i, o) \
/** actor */ i(entity, MUTATOR_ARGV_0_entity) \
/** weapon entity */ i(entity, MUTATOR_ARGV_1_entity) \
+ /** ammo to take */ i(float, MUTATOR_ARGV_2_float) \
+ /**/ o(float, MUTATOR_ARGV_2_float) \
/**/
MUTATOR_HOOKABLE(W_DecreaseAmmo, EV_W_DecreaseAmmo);
/**/
MUTATOR_HOOKABLE(SetResourceAmount, EV_SetResourceAmount);
+/** Called after the amount of resource of an entity has changed. See RESOURCE_*
+constants for resource types. Amount wasted is the amount of resource that is
+above resource limit so it was not given. */
+#define EV_ResourceAmountChanged(i, o) \
+ /** checked entity */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** resource type */ i(int, MUTATOR_ARGV_1_int) \
+ /** amount */ i(float, MUTATOR_ARGV_2_float) \
+ /**/
+MUTATOR_HOOKABLE(ResourceAmountChanged, EV_ResourceAmountChanged);
+
+/** Called when there was an attempt to set entity resources higher than their
+limit. See RESOURCE_* constants for resource types. Amount wasted is the amount
+of resource that is above resource limit so it was not given. */
+#define EV_ResourceWasted(i, o) \
+ /** checked entity */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** resource type */ i(int, MUTATOR_ARGV_1_int) \
+ /** amount wasted */ i(float, MUTATOR_ARGV_2_float) \
+ /**/
+MUTATOR_HOOKABLE(ResourceWasted, EV_ResourceWasted);
+
/** Called when entity is being given some resource. See RESOURCE_* constants
for resource types. Return true to forbid giving. */
#define EV_GiveResource(i, o) \
/**/
MUTATOR_HOOKABLE(GiveResource, EV_GiveResource);
+/** Called when entity is being given some resource with specified limit. See
+RESOURCE_* constants for resource types. Return true to forbid giving. */
+#define EV_GiveResourceWithLimit(i, o) \
+ /** receiver */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** resource type */ i(int, MUTATOR_ARGV_1_int) \
+ /**/ o(int, MUTATOR_ARGV_1_int) \
+ /** amount */ i(float, MUTATOR_ARGV_2_float) \
+ /**/ o(float, MUTATOR_ARGV_2_float) \
+ /** limit */ i(float, MUTATOR_ARGV_3_float) \
+ /**/ o(float, MUTATOR_ARGV_3_float) \
+ /**/
+MUTATOR_HOOKABLE(GiveResourceWithLimit, EV_GiveResourceWithLimit);
+
/** called at when a player connect */
#define EV_ClientConnect(i, o) \
/** player */ i(entity, MUTATOR_ARGV_0_entity) \
/** player */ i(entity, MUTATOR_ARGV_0_entity) \
/**/
MUTATOR_HOOKABLE(CalculateRespawnTime, EV_CalculateRespawnTime);
+
+/** called when parsing a vote command. */
+#define EV_VoteCommand_Parse(i, o) \
+ /** caller */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** first command */ i(string, MUTATOR_ARGV_1_string) \
+ /** vote command */ i(string, MUTATOR_ARGV_2_string) \
+ /** start position of vote command */ i(float, MUTATOR_ARGV_3_float) \
+ /** argument count */ i(float, MUTATOR_ARGV_4_float) \
+ /**/
+MUTATOR_HOOKABLE(VoteCommand_Parse, EV_VoteCommand_Parse);
+
+enum {
+ MUT_VOTEPARSE_CONTINUE, // return this flag to make the function continue as normal
+ MUT_VOTEPARSE_SUCCESS, // return 1 (vote parsed)
+ MUT_VOTEPARSE_INVALID, // return -1 (vote parsed but counted as invalid, no action or vote)
+ MUT_VOTEPARSE_UNACCEPTABLE // return 0 (vote parameter counted as unacceptable, warns caller)
+};
if(player.stored_netname != player.netname)
{
db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
- strunzone(player.stored_netname);
- player.stored_netname = strzone(player.netname);
+ strcpy(player.stored_netname, player.netname);
}
}
}
if(player.stored_netname != player.netname)
{
db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
- strunzone(player.stored_netname);
- player.stored_netname = strzone(player.netname);
+ strcpy(player.stored_netname, player.netname);
}
}
if(player.stored_netname != player.netname)
{
db_put(ServerProgsDB, strcat("/uid2name/", player.crypto_idfp), player.netname);
- strunzone(player.stored_netname);
- player.stored_netname = strzone(player.netname);
+ strcpy(player.stored_netname, player.netname);
}
}
}
race_SendRankings(newpos, player_prevpos, 0, MSG_ALL);
- if(rankings_reply)
- strunzone(rankings_reply);
- rankings_reply = strzone(getrankings());
+ strcpy(rankings_reply, getrankings());
if(newpos == player_prevpos)
{
if(pos == 1)
race_send_recordtime(MSG_ALL);
- if(rankings_reply)
- strunzone(rankings_reply);
- rankings_reply = strzone(getrankings());
+ strcpy(rankings_reply, getrankings());
}
void race_SendTime(entity e, float cp, float t, float tvalid)
if(t < recordtime || recordtime == 0)
{
race_checkpoint_records[cp] = t;
- if(race_checkpoint_recordholders[cp])
- strunzone(race_checkpoint_recordholders[cp]);
- race_checkpoint_recordholders[cp] = strzone(e.netname);
+ strcpy(race_checkpoint_recordholders[cp], e.netname);
if(g_race_qualifying)
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.race_checkpoint == cp, { race_SendNextCheckpoint(it, 0); });
}
for(int j = 0; j < MAX_CHECKPOINTS; ++j)
{
race_checkpoint_records[j] = 0;
- if(race_checkpoint_recordholders[j])
- strunzone(race_checkpoint_recordholders[j]);
- race_checkpoint_recordholders[j] = string_null;
+ strfree(race_checkpoint_recordholders[j]);
}
FOREACH_CLIENT(true, {
}
resource_type = M_ARGV(1, int);
amount = M_ARGV(2, float);
- .float resource_field = GetResourceField(resource_type);
- if (e.(resource_field) == amount)
- {
- return;
- }
float max_amount = GetResourceLimit(e, resource_type);
+ float amount_wasted = 0;
if (amount > max_amount)
{
+ amount_wasted = amount - max_amount;
amount = max_amount;
}
- e.(resource_field) = amount;
+ .float resource_field = GetResourceField(resource_type);
+ if (e.(resource_field) != amount)
+ {
+ e.(resource_field) = amount;
+ MUTATOR_CALLHOOK(ResourceAmountChanged, e, resource_type, amount);
+ }
+ if (amount_wasted == 0)
+ {
+ return;
+ }
+ MUTATOR_CALLHOOK(ResourceWasted, e, resource_type, amount_wasted);
}
void GiveResource(entity receiver, int resource_type, float amount)
void GiveResourceWithLimit(entity receiver, int resource_type, float amount,
float limit)
{
+ if (amount == 0)
+ {
+ return;
+ }
+ bool forbid = MUTATOR_CALLHOOK(GiveResourceWithLimit, receiver,
+ resource_type, amount, limit);
+ if (forbid)
+ {
+ return;
+ }
+ resource_type = M_ARGV(1, int);
+ amount = M_ARGV(2, float);
+ limit = M_ARGV(3, float);
if (amount == 0)
{
return;
}
}
- if(worldstatus)
- strunzone(worldstatus);
- worldstatus = strzone(s);
+ strcpy(worldstatus, s);
FOREACH_CLIENT(true, {
string s = "";
s = "-666";
}
- if(it.clientstatus)
- strunzone(it.clientstatus);
- it.clientstatus = strzone(s);
+ strcpy(it.clientstatus, s);
});
}
}
return;
LABEL(cleanup)
- builtin_remove(this);
+ delete(this);
}
void WarpZone_PostInitialize_Callback()
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
- if(cache_lastmutatormsg)
- strunzone(cache_lastmutatormsg);
- if(cache_mutatormsg)
- strunzone(cache_mutatormsg);
- cache_lastmutatormsg = strzone(autocvar_g_mutatormsg);
- cache_mutatormsg = strzone(cache_lastmutatormsg);
+ strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg);
+ strcpy(cache_mutatormsg, cache_lastmutatormsg);
}
if (cache_mutatormsg != "") {
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
{
- if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity))) return;
+ if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity), ammo_use)) return;
if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
+ ammo_use = M_ARGV(2, float);
+
entity w_ent = actor.(weaponentity);
// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
this.reload_ammo_min = sent_ammo_min;
this.reload_ammo_amount = e.reloading_ammo;
this.reload_time = e.reloading_time;
- if (actor.reload_sound) strunzone(actor.reload_sound);
- actor.reload_sound = strzone(Sound_fixpath(sent_sound));
+ strcpy(actor.reload_sound, Sound_fixpath(sent_sound));
// don't reload weapons that don't have the RELOADABLE flag
if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
--- /dev/null
+exec xonotic-server.cfg
+
+exec balance-nexuiz25.cfg
+exec physicsNexuiz26.cfg
+
+sv_gameplayfix_delayprojectiles 1
+
+// new toys to restore the weapons
+g_new_toys 1
+g_new_toys_autoreplace 0
+g_new_toys_use_pickupsound 0
set g_waypointeditor 0
set g_waypointeditor_auto 0 "Automatically create waypoints for bots while playing; BEWARE, this currently creates too many of them"
set g_waypointeditor_symmetrical 0 "Enable symmetrical editing of waypoints on symmetrical CTF maps (NOTE: it assumes that the map is perfectly symmetrical). 1: automatically determine origin of symmetry; -1: use custom origin (g_waypointeditor_symmetrical_origin); 2: automatically determine axis of symmetry; -2: use custom axis (g_waypointeditor_symmetrical_axis)"
+set g_waypointeditor_symmetrical_allowload 1 "Allow loading symmetry settings from waypoint files into g_waypointeditor_symmetrical* cvars on map start"
set g_waypointeditor_symmetrical_origin "0 0" "Custom origin of symmetry (x y)"
set g_waypointeditor_symmetrical_order 0 "if >= 2 apply rotational symmetry (around origin of symmetry) of this order, otherwise apply autodetected order of symmetry"
set g_waypointeditor_symmetrical_axis "0 0" "Custom axis of symmetry (m q parameters of y = mx + q)"
set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
set g_spawnshield_blockdamage 1 "how much spawn shield protects you from damage (1 = full protection)"
-set g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
+set g_antilag 2 "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past)"
set g_antilag_nudge 0 "don't touch"
set g_shootfromeye 0 "shots are fired from your eye/crosshair; visual gun position can still be influenced by cl_gunalign 1 and 2"
set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"