entity clearentity_ent;
void clearentity(entity e)
{
- if not(clearentity_ent)
+ if (!clearentity_ent)
{
clearentity_ent = spawn();
clearentity_ent.classname = "clearentity";
check_unacceptable_compiler_bugs();
#ifdef WATERMARK
- print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK));
+ printf(_("^4CSQC Build information: ^1%s\n"), WATERMARK);
#endif
float i;
//registercommand("hud_configure");
//registercommand("hud_save");
//registercommand("menu_action");
-
+
ConsoleCommand_macro_init();
registercvar("hud_usecsqc", "1");
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
+ CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
Casings_Precache();
DamageInfo_Precache();
Vehicles_Precache();
- turrets_precache();
Tuba_Precache();
CSQCPlayer_Precache();
-
+
if(autocvar_cl_reticle)
{
if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
}
-
+
get_mi_min_max_texcoords(1); // try the CLEVER way first
minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
shortmapname = mi_shortname;
if(autocvar_chase_active < 0)
cvar_set("chase_active", "0");
- if not(isdemo())
+ if (!isdemo())
{
- if not(calledhooks & HOOK_START)
+ if (!(calledhooks & HOOK_START))
localcmd("\n_cl_hook_gamestart nop\n");
- if not(calledhooks & HOOK_END)
+ if (!(calledhooks & HOOK_END))
localcmd("\ncl_hook_gameend\n");
}
}
default:
if(GetTeam(Team, false) == world)
{
- print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+ printf(_("trying to switch to unsupported team %d\n"), Team);
Team = NUM_SPECTATOR;
}
break;
default:
if(GetTeam(Team, false) == world)
{
- print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+ printf(_("trying to switch to unsupported team %d\n"), Team);
Team = NUM_SPECTATOR;
}
break;
}
else
{
- if not(o.has_team)
+ if (!o.has_team)
{
o.team = Team;
tm = GetTeam(Team, true);
}
else
{
- if not(e.sort_prev)
+ if (!e.sort_prev)
{
// player connected
- if not(e)
+ if (!e)
playerslots[i] = e = spawn();
e.sv_entnum = i;
e.ping = 0;
if(!isNew && n != self.sv_entnum)
{
//print("A CSQC entity changed its owner!\n");
- print(sprintf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname));
+ printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
isNew = true;
Ent_Remove();
self.enttype = ENT_CLIENT_SCORES;
self.sv_entnum = n;
- if not(playerslots[self.sv_entnum])
+ if (!(playerslots[self.sv_entnum]))
playerslots[self.sv_entnum] = spawn();
o = self.owner = playerslots[self.sv_entnum];
o.sv_entnum = self.sv_entnum;
o.gotscores = 1;
- //if not(o.sort_prev)
+ //if (!o.sort_prev)
// RegisterPlayer(o);
//playerchecker will do this for us later, if it has not already done so
{
f = ReadByte();
for(j = i-1, b = 1; b < 256; b *= 2, ++j)
- if not(f & b)
+ if (!(f & b))
if(playerslots[j])
playerslots[j].ready = 0;
}
spn_origin_x = ReadShort();
spn_origin_y = ReadShort();
spn_origin_z = ReadShort();
-
+
if(is_new)
{
self.origin = spn_origin;
}
}
else { self.cnt = particleeffectnum("spawn_point_neutral"); }
-
+
self.draw = Spawn_Draw;
}
}
- //print(sprintf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt));
+ //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt);
}
void Ent_ReadSpawnEvent(float is_new)
// this way the server can disable the sending of
// spawn origin or such to clients if wanted.
float entnum = ReadByte();
-
+
if(entnum)
{
self.origin_x = ReadShort();
}
}
}
-
+
// local spawn actions
if(is_new && (!entnum || (entnum == player_localentnum)))
{
button_zoom = FALSE;
}
}
-
- //print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum));
+
+ //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
}
// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
t = ReadByte();
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t));
+ printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
// set up the "time" global for received entities to be correct for interpolation purposes
savetime = time;
if(t != self.enttype || bIsNewEntity)
{
//print("A CSQC entity changed its type!\n");
- print(sprintf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t));
+ printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
Ent_Remove();
clearentity(self);
bIsNewEntity = 1;
{
if(!bIsNewEntity)
{
- print(sprintf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t));
+ printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
bIsNewEntity = 1;
}
}
case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
- case ENT_CLIENT_TURRET: ent_turret(); break;
+ case ENT_CLIENT_TURRET: ent_turret(); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
- case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
+ case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
void CSQC_Ent_Remove()
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype));
+ printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
if(wasfreed(self))
{
void Gamemode_Init()
{
- if not(isdemo())
+ if (!isdemo())
{
if(!(calledhooks & HOOK_START))
localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n");
void CSQC_Parse_StuffCmd(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
localcmd(strMessage);
}
void CSQC_Parse_Print(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_Print(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
print(ColorTranslateRGB(strMessage));
}
void CSQC_Parse_CenterPrint(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
centerprint_hud(strMessage);
}
{
// TODO somehow thwart prvm_globalset client ...
- if(forcefog != "")
- localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2));
+ if(autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
+ { localcmd("\nr_drawfog 0\n"); }
+ else if(forcefog != "")
+ { localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2)); }
}
void Gamemode_Init();
float i;
self.classname = "ent_client_scores_info";
gametype = ReadInt24_t();
+ HUD_ModIcons_SetFunc();
for(i = 0; i < MAX_SCORE; ++i)
{
scores_label[i] = strzone(ReadString());
pi = ReadShort();
pl = ReadByte();
ml = ReadByte();
- if not(playerslots[e])
+ if (!(playerslots[e]))
return;
playerslots[e].ping = pi;
playerslots[e].ping_packetloss = pl / 255.0;
nTEID = ReadByte();
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID));
+ printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
// NOTE: Could just do return instead of break...
switch(nTEID)
Net_ReadRace();
bHandled = true;
break;
- case TE_CSQC_ZCURVEPARTICLES:
- Net_ReadZCurveParticles();
- bHandled = true;
- break;
case TE_CSQC_NEXGUNBEAMPARTICLE:
Net_ReadNexgunBeamParticle();
bHandled = true;
e = get_weaponinfo(type);
effectname = strcat("damage_", e.netname);
-
+
// if damage was dealt with a bullet weapon, our effect is blood
// since blood is species dependent, include the species tag
if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
force = decompressShortVector(ReadShort());
species = ReadByte();
- if not(isNew)
+ if (!isNew)
return;
if(rad < 0)
}
else
forcemul = 1;
-
+
for(self = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); self; self = self.chain)
{
// attached ents suck
}
self = oldself;
-
+
if(DEATH_ISVEHICLE(w_deathtype))
{
traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world);
w_backoff = trace_plane_normal;
else
w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16));
-
+
setorigin(self, w_org + w_backoff * 2); // for sound() calls
-
+
switch(w_deathtype)
{
case DEATH_VH_CRUSH:
break;
-
+
// spiderbot
case DEATH_VH_SPID_MINIGUN:
string _snd;
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
break;
-
+
case DEATH_VH_WAKI_GUN:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum("wakizashi_gun_impact"), self.origin, w_backoff * 1000, 1);
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
break;
-
+
case DEATH_VH_RAPT_CANNON:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum("raptor_cannon_impact"), self.origin, w_backoff * 1000, 1);
break;
}
}
-
-
+
+
if(DEATH_ISTURRET(w_deathtype))
{
string _snd;
w_backoff = trace_plane_normal;
else
w_backoff = -1 * normalize(w_org - (w_org + normalize(force) * 16));
-
+
setorigin(self, w_org + w_backoff * 2); // for sound() calls
-
+
switch(w_deathtype)
- {
+ {
case DEATH_TURRET_EWHEEL:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("laser_impact"), self.origin, w_backoff * 1000, 1);
break;
-
+
case DEATH_TURRET_FLAC:
pointparticles(particleeffectnum("hagar_explode"), w_org, '0 0 0', 1);
_snd = strcat("weapons/hagexp", ftos(1 + rint(random() * 2)), ".waw");
sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
break;
-
+
case DEATH_TURRET_MLRS:
case DEATH_TURRET_HK:
case DEATH_TURRET_WALK_ROCKET:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("rocket_explode"), self.origin, w_backoff * 1000, 1);
break;
-
+
case DEATH_TURRET_MACHINEGUN:
case DEATH_TURRET_WALK_GUN:
_snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw");
sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum("machinegun_impact"), self.origin, w_backoff * 1000, 1);
break;
-
+
case DEATH_TURRET_PLASMA:
sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1);
break;
-
+
- case DEATH_TURRET_WALK_MEELE:
+ case DEATH_TURRET_WALK_MELEE:
sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_MIN);
pointparticles(particleeffectnum("TE_SPARK"), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_PHASER:
break;
-
+
case DEATH_TURRET_TESLA:
te_smallflash(self.origin);
break;
}
}
-
+
// TODO spawn particle effects and sounds based on w_deathtype
if(!DEATH_ISSPECIAL(w_deathtype))
- if not(hitplayer && !rad) // don't show ground impacts for hitscan weapons if a player was hit
+ if(!hitplayer || rad) // don't show ground impacts for hitscan weapons if a player was hit
{
float hitwep;
../common/animdecide.qh
command/cl_cmd.qh
+ ../common/monsters/monsters.qh
+
autocvars.qh
../common/notifications.qh // must be after autocvars
../common/deathtypes.qh // must be after notifications
+../common/turrets/turrets.qh
+../common/turrets/cl_turrets.qh
+
damage.qh
../csqcmodellib/interpolate.qh
prandom.qh
bgmscript.qh
noise.qh
-tturrets.qh
-../server/tturrets/include/turrets_early.qh
../server/movelib.qc
main.qh
vehicles/vehicles.qh
../common/urllib.qc
command/cl_cmd.qc
+ ../common/monsters/monsters.qc
+
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
../warpzonelib/common.qc
../warpzonelib/client.qc
-tturrets.qc
+
+../common/turrets/cl_turrets.qc
+../common/turrets/turrets.qc
player_skeleton.qc
../common/animdecide.qc
-
- ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
do_cvar = curl_uri_get_cvar[i];
if(status != 0)
{
- print(sprintf(_("error: status is %d\n"), status));
+ printf(_("error: status is %d\n"), status);
if(do_cvar)
strunzone(do_cvar);
return;
strunzone(do_cvar);
}
if(!do_exec)
- if not(do_cvar)
+ if (!do_cvar)
print(data);
}
case CMD_REQUEST_COMMAND:
{
float i;
-
+
if(argc >= 2)
{
string original_cvar = argv(1);
string tmp_string = argv(2);
-
+
if(cvar_string(original_cvar) == "") // cvar was empty
{
cvar_set(original_cvar, tmp_string);
else // add it to the end of the list if the list doesn't already have it
{
argc = tokenizebyseparator(cvar_string(original_cvar), " ");
-
+
for(i = 0; i < argc; ++i)
if(argv(i) == tmp_string)
return; // already in list
-
+
cvar_set(original_cvar, strcat(tmp_string, " ", cvar_string(original_cvar)));
}
return;
}
}
-
+
default:
print("Incorrect parameters for ^2addtolist^7\n");
case CMD_REQUEST_USAGE:
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
float fh;
string filename = strcat(GetProgramCommandPrefix(), "_dump.txt");
fh = fopen(filename, FILE_WRITE);
-
+
if(fh >= 0)
{
#ifdef SVQC
CMD_Write("dump of server console commands:\n");
GameCommand_macro_write_aliases(fh);
-
+
CMD_Write("\ndump of networked client only commands:\n");
ClientCommand_macro_write_aliases(fh);
-
+
CMD_Write("\ndump of common commands:\n");
CommonCommand_macro_write_aliases(fh);
CMD_Write("\ndump of ban commands:\n");
BanCommand_macro_write_aliases(fh);
#endif
-
+
#ifdef CSQC
CMD_Write("dump of client commands:\n");
LocalCommand_macro_write_aliases(fh);
#endif
-
+
CMD_Write("\ndump of generic commands:\n");
GenericCommand_macro_write_aliases(fh);
-
+
print("Completed dump of aliases in ^2data/data/", GetProgramCommandPrefix(), "_dump.txt^7.\n");
-
+
fclose(fh);
}
else
}
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
#ifndef MENUQC
float fh, alsoprint = FALSE;
string filename = argv(1);
-
+
if(filename == "")
{
filename = "notifications.cfg";
alsoprint = TRUE;
}
fh = fopen(filename, FILE_WRITE);
-
+
if(fh >= 0)
{
Dump_Notifications(fh, alsoprint);
- print(sprintf("Dumping notifications... File located in ^2data/data/%s^7.\n", filename));
+ printf("Dumping notifications... File located in ^2data/data/%s^7.\n", filename);
fclose(fh);
}
else
{
- print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+ printf("^1Error: ^7Could not open file '%s'!\n", filename);
}
#else
print(_("Notification dump command only works with cl_cmd and sv_cmd.\n"));
#endif
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
}
}
+void GenericCommand_dumpturrets(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ #ifdef SVQC
+ tur_config_file = -1;
+ tur_config_alsoprint = -1;
+ string filename = argv(1);
+
+ if(filename == "")
+ {
+ filename = "turrets_dump.cfg";
+ tur_config_alsoprint = FALSE;
+ }
+ else if(filename == "-")
+ {
+ filename = "turrets_dump.cfg";
+ tur_config_alsoprint = TRUE;
+ }
+ tur_config_file = fopen(filename, FILE_WRITE);
+
+ if(tur_config_file >= 0)
+ {
+ Dump_Turret_Settings();
+ print(sprintf("Dumping turrets... File located in ^2data/data/%s^7.\n", filename));
+ fclose(tur_config_file);
+ tur_config_file = -1;
+ tur_config_alsoprint = -1;
+ }
+ else
+ {
+ print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+ }
+ #else
+ print(_("Turrets dump command only works with sv_cmd.\n"));
+ #endif
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpturrets [filename]"));
+ print(" Where 'filename' is the file to write (default is turrets_dump.cfg),\n");
+ print(" if supplied with '-' output to console as well as default,\n");
+ print(" if left blank, it will only write to default.\n");
+ return;
+ }
+ }
+}
+
void GenericCommand_maplist(float request, float argc)
{
switch(request)
{
string tmp_string;
float i;
-
+
switch(argv(1))
{
case "add": // appends new maps to the maplist
print("maplist: ERROR: ", argv(2), " does not exist!\n");
break;
}
-
+
if(cvar_string("g_maplist") == "")
cvar_set("g_maplist", argv(2));
else
cvar_set("g_maplist", strcat(argv(2), " ", cvar_string("g_maplist")));
-
+
return;
}
break; // go to usage
}
-
+
case "cleanup": // scans maplist and only adds back the ones which are really usable
{
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
argc = tokenizebyseparator(cvar_string("g_maplist"), " ");
-
+
tmp_string = "";
for(i = 0; i < argc; ++i)
if(MapInfo_CheckMap(argv(i)))
tmp_string = strcat(tmp_string, " ", argv(i));
-
+
tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1);
cvar_set("g_maplist", tmp_string);
-
+
return;
}
-
+
case "remove": // scans maplist and only adds back whatever maps were not provided in argv(2)
{
if(argc == 3)
{
argc = tokenizebyseparator(cvar_string("g_maplist"), " ");
-
+
tmp_string = "";
for(i = 0; i < argc; ++i)
if(argv(i) != argv(2))
tmp_string = strcat(tmp_string, " ", argv(i));
-
+
tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1);
cvar_set("g_maplist", tmp_string);
-
+
return;
}
break; // go to usage
}
-
+
case "shuffle": // randomly shuffle the maplist
{
cvar_set("g_maplist", shufflewords(cvar_string("g_maplist")));
return;
}
-
+
default: break;
}
}
-
+
default:
print("Incorrect parameters for ^2maplist^7\n");
case CMD_REQUEST_USAGE:
queue_to_execute_next_frame(substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
string original_cvar = argv(1);
string removal = argv(2);
string tmp_string;
-
+
argc = tokenizebyseparator(cvar_string(original_cvar), " ");
-
+
tmp_string = "";
for(i = 0; i < argc; ++i)
if(argv(i) != removal)
tmp_string = strcat(tmp_string, " ", argv(i));
-
+
tmp_string = substring(tmp_string, 1, strlen(tmp_string) - 1);
cvar_set(original_cvar, tmp_string);
-
+
return;
}
}
-
+
default:
print("Incorrect parameters for ^2removefromlist^7\n");
case CMD_REQUEST_USAGE:
case CMD_REQUEST_COMMAND:
{
#ifndef MENUQC
- print(sprintf(
+ printf(
strcat(
"Restart_Notifications(): Restarting %d notifications... ",
"Counts: MSG_ANNCE = %d, MSG_INFO = %d, MSG_CENTER = %d, MSG_MULTI = %d, MSG_CHOICE = %d\n"
NOTIF_CENTER_COUNT,
NOTIF_MULTI_COUNT,
NOTIF_CHOICE_COUNT
- ));
+ );
Destroy_All_Notifications();
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
#else
#endif
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
{
float f = cvar_settemp(argv(1), argv(2));
if(f == 1)
- dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n");
+ dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n");
else if(f == -1)
dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
// else cvar_settemp itself errors out
case CMD_REQUEST_COMMAND:
{
float i = cvar_settemp_restore();
-
+
if(i)
dprint("Restored ", ftos(i), " temporary cvar settings to their original values.\n");
else
dprint("Nothing to restore.\n");
-
+
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
TEST_RunAll();
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
{
case CMD_REQUEST_COMMAND:
{
-
+
return;
}
-
+
default:
case CMD_REQUEST_USAGE:
{
GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
+ GENERIC_COMMAND("dumpturrets", GenericCommand_dumpturrets(request), "Dump all turrets into turrets_dump.txt") \
GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \
GENERIC_COMMAND("qc_curl", GenericCommand_qc_curl(request, arguments), "Queries a URL") \
{
#define GENERIC_COMMAND(name,function,description) \
{ print(" ^2", name, "^7: ", description, "\n"); }
-
+
GENERIC_COMMANDS(0, 0, "")
#undef GENERIC_COMMAND
-
+
return;
}
{
#define GENERIC_COMMAND(name,function,description) \
{ if(name == strtolower(argv(0))) { function; return TRUE; } }
-
+
GENERIC_COMMANDS(CMD_REQUEST_COMMAND, argc, command)
#undef GENERIC_COMMAND
-
+
return FALSE;
}
{
#define GENERIC_COMMAND(name,function,description) \
{ if(name == strtolower(argv(1))) { function; return TRUE; } }
-
+
GENERIC_COMMANDS(CMD_REQUEST_USAGE, argc, "")
#undef GENERIC_COMMAND
-
+
return FALSE;
}
{
#define GENERIC_COMMAND(name,function,description) \
{ CMD_Write_Alias("qc_cmd_svmenu", name, description); }
-
+
GENERIC_COMMANDS(0, 0, "")
#undef GENERIC_COMMAND
-
+
return;
}
-
+
// ===========================================
// Main Common Function For Generic Commands
// ===========================================
- // Commands spread out among all programs (menu, client, and server)
+ // Commands spread out among all programs (menu, client, and server)
float GenericCommand(string command)
{
// Guide for working with argc arguments by example:
// argc: 1 - 2 - 3 - 4
- // argv: 0 - 1 - 2 - 3
+ // argv: 0 - 1 - 2 - 3
// cmd vote - master - login - password
-
+
if(GenericCommand_macro_command(argc, command)) // continue as usual and scan for normal commands
{
return TRUE; // handled by one of the above GenericCommand_* functions
// test case for terencehill's color codes
s = strdecolorize(substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
s2 = "";
-
+
n = strlen(s);
j = ((6 * max(1, floor(strlen(s)/32 + random() * 2 - 1))) / n) * (1 - 2 * (random() > 0.5));
f = random() * 6;
DEATHTYPE(DEATH_KILL, DEATH_SELF_SUICIDE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_LAVA, DEATH_SELF_LAVA, DEATH_MURDER_LAVA, NORMAL_POS) \
DEATHTYPE(DEATH_MIRRORDAMAGE, DEATH_SELF_BETRAYAL, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_MAGE, DEATH_SELF_MON_MAGE, DEATH_MURDER_MONSTER, DEATH_MONSTER_FIRST) \
+ DEATHTYPE(DEATH_MONSTER_SHAMBLER_CLAW, DEATH_SELF_MON_SHAMBLER_CLAW, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_SHAMBLER_SMASH, DEATH_SELF_MON_SHAMBLER_SMASH, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_SHAMBLER_ZAP, DEATH_SELF_MON_SHAMBLER_ZAP, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_SPIDER, DEATH_SELF_MON_SPIDER, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_WYVERN, DEATH_SELF_MON_WYVERN, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_ZOMBIE_JUMP, DEATH_SELF_MON_ZOMBIE_JUMP, DEATH_MURDER_MONSTER, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_ZOMBIE_MELEE, DEATH_SELF_MON_ZOMBIE_MELEE, DEATH_MURDER_MONSTER, DEATH_MONSTER_LAST) \
DEATHTYPE(DEATH_NADE, DEATH_SELF_NADE, DEATH_MURDER_NADE, NORMAL_POS) \
DEATHTYPE(DEATH_NOAMMO, DEATH_SELF_NOAMMO, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_ROT, DEATH_SELF_ROT, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_PLASMA, DEATH_SELF_TURRET_PLASMA, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_TESLA, DEATH_SELF_TURRET_TESLA, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_WALK_GUN, DEATH_SELF_TURRET_WALK_GUN, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_TURRET_WALK_MEELE, DEATH_SELF_TURRET_WALK_MEELE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_WALK_MELEE, DEATH_SELF_TURRET_WALK_MELEE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_TURRET_WALK_ROCKET, DEATH_SELF_TURRET_WALK_ROCKET, NO_MSG, DEATH_TURRET_LAST) \
DEATHTYPE(DEATH_VH_BUMB_DEATH, DEATH_SELF_VH_BUMB_DEATH, DEATH_MURDER_VH_BUMB_DEATH, DEATH_VHFIRST) \
DEATHTYPE(DEATH_VH_BUMB_GUN, NO_MSG, DEATH_MURDER_VH_BUMB_GUN, NORMAL_POS) \
#define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START)
#define DEATH_ISVEHICLE(t) ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST)
#define DEATH_ISTURRET(t) ((t) >= DEATH_TURRET_FIRST && (t) <= DEATH_TURRET_LAST)
+ #define DEATH_ISMONSTER(t) ((t) >= DEATH_MONSTER_FIRST && (t) <= DEATH_MONSTER_LAST)
#define DEATH_WEAPONOFWEAPONDEATH(t) ((t) & DEATH_WEAPONMASK)
#define DEATH_ISWEAPON(t,w) (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w))
#define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? 0 : DEATH_WEAPONOFWEAPONDEATH(t))
if(DEATH_ISSPECIAL(deathtype))
{
entity deathent = deathtypes[(deathtype - DT_FIRST)];
- if not(deathent) { backtrace("Deathtype_Name: Could not find deathtype entity!\n"); return ""; }
+ if (!deathent) { backtrace("Deathtype_Name: Could not find deathtype entity!\n"); return ""; }
return deathent.nent_name;
}
else { return ftos(deathtype); }
// main types/groups of notifications
#define MSG_ANNCE 1 // "Global" AND "personal" announcer messages
- #define MSG_INFO 2 // "Global" information messages
+ #define MSG_INFO 2 // "Global" information messages
#define MSG_CENTER 3 // "Personal" centerprint messages
#define MSG_CENTER_CPID 4 // Kill centerprint message
#define MSG_MULTI 5 // Subcall MSG_INFO and/or MSG_CENTER notifications
float strnum,
float flnum,
/* MSG_ANNCE */
- float channel,
+ float channel,
string snd,
float vol,
float position,
Check out the definitions in util.qc/util.qh/teams.qh for string CCR(...) and
string TCR(...) to better understand how these code replacements work.
-
+
Additionally, you can find all the definitions and explanations for
the argument values and what they return down below in this file.
MULTITEAM_INFO##teams(default,prefix,strnum,flnum,args,hudargs,icon,normal,gentle)
#define MSG_INFO_NOTIFICATIONS \
+ MSG_INFO_NOTIF(2, INFO_CHAT_NOSPECTATORS, 0, 0, "", "", "", _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 2, 1, 0, "s1", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_BROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_TIME_, 2, 1, 1, "s1 f1p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"), "") \
MULTITEAM_INFO(1, INFO_CTF_LOST_, 2, 1, 0, "s1", "s1", "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag"), "") \
MULTITEAM_INFO(1, INFO_CTF_PICKUP_, 2, 1, 0, "s1", "s1", "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag"), "") \
MULTITEAM_INFO(1, INFO_CTF_RETURN_, 2, 1, 0, "s1", "s1", "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_RETURN_MONSTER_, 2, 1, 0, "s1", "s1", "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_CHEAT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_DROWN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_water", _("^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FALL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_fall", _("^BG%s%s^K1 was grounded by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FIRE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"), _("^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_LAVA, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_lava", _("^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_MONSTER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was pushed infront of a monster by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SHOOTING_STAR, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_shootingstar", _("^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SLIME, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_GENERIC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 died%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_LAVA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_lava", _("^BG%s^K1 turned into hot slag%s%s"), _("^BG%s^K1 found a hot place%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MAGE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was exploded by a Mage%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1's innards became outwards by a Shambler%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was smashed by a Shambler%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_ZAP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was zapped to death by a Shambler%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was bitten by a Spider%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fireballed by a Wyvern%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 joins the Zombies%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_outofammo", _("^BG%s^K1 died%s%s. What's the point of living without ammo?"), _("^BG%s^K1 ran out of ammo%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 rotted away%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SHOOTING_STAR, 2, 1, "s1 s2loc spree_lost", "s1", "notify_shootingstar", _("^BG%s^K1 became a shooting star%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PLASMA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served some superheated plasma from a turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_TESLA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was electrocuted by a Tesla turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_GUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MEELE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Walker turret%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_BUMB_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a vehicle%s%s"), "") \
MULTITEAM_INFO(1, INFO_KEYHUNT_PICKUP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG picked up the ^TC^TT Key"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left"), "") \
+ MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED, 0, 0, "", "", "", _("^BGMonsters are currently disabled"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed"), "") \
MSG_INFO_NOTIF(2, INFO_QUIT_KICK_IDLING, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling"), "") \
MSG_INFO_NOTIF(1, INFO_QUIT_KICK_SPECTATING, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "") \
MSG_INFO_NOTIF(1, INFO_QUIT_SPECTATE, 1, 0, "s1", "", "", _("^BG%s^F3 is now spectating"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_ABANDONED, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_FAIL_RANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_FAIL_UNRANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_FINISHED, 1, 0, "s1", "", "", _("^BG%s^BG has finished the race"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_NEW_BROKEN, 2, 3, "s1 s2 race_col f1ord race_col f2race_time race_diff", "s1 s2", "race_newrankyellow", _("^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_NEW_IMPROVED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newtime", _("^BG%s^BG improved their %s%s^BG place record with %s%s %s"), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_NEW_MISSING_UID, 1, 1, "s1 f1race_time", "s1", "race_newfail", _("^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID and will be lost."), "") \
- MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_ABANDONED, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FAIL_RANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1 f3race_time", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FAIL_UNRANKED, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1 f3race_time", "race_newfail", _("^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FINISHED, 1, 0, "s1", "", "", _("^BG%s^BG has finished the race"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_BROKEN, 2, 3, "s1 s2 race_col f1ord race_col f2race_time race_diff", "s1 f2race_time", "race_newrankyellow", _("^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_IMPROVED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1 f2race_time", "race_newtime", _("^BG%s^BG improved their %s%s^BG place record with %s%s %s"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_MISSING_UID, 1, 1, "s1 f1race_time", "s1 f1race_time", "race_newfail", _("^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID and will be lost."), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1 f2race_time", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s"), "") \
MULTITEAM_INFO(1, INFO_SCORES_, 4, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!"), "") \
MSG_INFO_NOTIF(1, INFO_SPECTATE_WARNING, 0, 1, "f1secs", "", "", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") \
MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up a Superweapon"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "")
+ MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "")
#define MULTITEAM_CENTER2(default,prefix,strnum,flnum,args,cpid,durcnt,normal,gentle) \
MSG_CENTER_NOTIF(default, prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_FIRE, 0, 0, "", NO_CPID, "0 0", _("^K1You got a little bit too crispy!"), _("^K1You felt a little too hot!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_GENERIC, 0, 0, "", NO_CPID, "0 0", _("^K1You killed your own dumb self!"), _("^K1You need to be more careful!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_LAVA, 0, 0, "", NO_CPID, "0 0", _("^K1You couldn't stand the heat!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_MONSTER, 0, 0, "", NO_CPID, "0 0", _("^K1You were killed by a monster!"), _("^K1You need to watch out for monsters!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE, 0, 0, "", NO_CPID, "0 0", _("^K1You forgot to put the pin back in!"), _("^K1Tastes like chicken!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NOAMMO, 0, 0, "", NO_CPID, "0 0", _("^K1You were killed for running out of ammo..."), _("^K1You are respawning for running out of ammo...")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_ROT, 0, 0, "", NO_CPID, "0 0", _("^K1You grew too old without taking your medicine"), _("^K1You need to preserve your health")) \
MSG_CENTER_NOTIF(1, CENTER_ROUND_PLAYER_WIN, 1, 0, "s1", CPID_ROUND, "0 0", _("^BG%s^BG wins the round"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SELF, 0, 0, "", NO_CPID, "0 0", _("^K1You froze yourself"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SPAWN_LATE, 0, 0, "", NO_CPID, "0 0", _("^K1Round already started, you spawn as frozen"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_INVASION_SUPERMONSTER, 1, 0, "s1", NO_CPID, "0 0", _("^K1A %s has arrived!"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^BGYou do not have the ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", CPID_ITEM, "item_centime 0", _("^BGYou dropped the ^F1%s^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_GOT, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^BGYou got the ^F1%s"), "") \
MSG_MULTI_NOTIF(1, DEATH_MURDER_FALL, NO_MSG, INFO_DEATH_MURDER_FALL, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_FIRE, NO_MSG, INFO_DEATH_MURDER_FIRE, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_LAVA, NO_MSG, INFO_DEATH_MURDER_LAVA, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_MONSTER, NO_MSG, INFO_DEATH_MURDER_MONSTER, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE, NO_MSG, INFO_DEATH_MURDER_NADE, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_SHOOTING_STAR, NO_MSG, INFO_DEATH_MURDER_SHOOTING_STAR, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_SLIME, NO_MSG, INFO_DEATH_MURDER_SLIME, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_SELF_FIRE, NO_MSG, INFO_DEATH_SELF_FIRE, CENTER_DEATH_SELF_FIRE) \
MSG_MULTI_NOTIF(1, DEATH_SELF_GENERIC, NO_MSG, INFO_DEATH_SELF_GENERIC, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, DEATH_SELF_LAVA, NO_MSG, INFO_DEATH_SELF_LAVA, CENTER_DEATH_SELF_LAVA) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_MAGE, NO_MSG, INFO_DEATH_SELF_MON_MAGE, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SHAMBLER_CLAW, NO_MSG, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SHAMBLER_SMASH, NO_MSG, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SHAMBLER_ZAP, NO_MSG, INFO_DEATH_SELF_MON_SHAMBLER_ZAP, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SPIDER, NO_MSG, INFO_DEATH_SELF_MON_SPIDER, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_WYVERN, NO_MSG, INFO_DEATH_SELF_MON_WYVERN, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_JUMP, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_MELEE, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_NADE, NO_MSG, INFO_DEATH_SELF_NADE, CENTER_DEATH_SELF_NADE) \
MSG_MULTI_NOTIF(1, DEATH_SELF_NOAMMO, NO_MSG, INFO_DEATH_SELF_NOAMMO, CENTER_DEATH_SELF_NOAMMO) \
MSG_MULTI_NOTIF(1, DEATH_SELF_ROT, NO_MSG, INFO_DEATH_SELF_ROT, CENTER_DEATH_SELF_ROT) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_PLASMA, NO_MSG, INFO_DEATH_SELF_TURRET_PLASMA, CENTER_DEATH_SELF_TURRET) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_TESLA, NO_MSG, INFO_DEATH_SELF_TURRET_TESLA, CENTER_DEATH_SELF_TURRET) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_GUN, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_GUN, CENTER_DEATH_SELF_TURRET_WALK) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_MEELE, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_MEELE, CENTER_DEATH_SELF_TURRET_WALK) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_MELEE, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_MELEE, CENTER_DEATH_SELF_TURRET_WALK) \
MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_ROCKET, NO_MSG, INFO_DEATH_SELF_TURRET_WALK_ROCKET, CENTER_DEATH_SELF_TURRET_WALK) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_BUMB_DEATH, NO_MSG, INFO_DEATH_SELF_VH_BUMB_DEATH, CENTER_DEATH_SELF_VH_BUMB_DEATH) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_CRUSH, NO_MSG, INFO_DEATH_SELF_VH_CRUSH, CENTER_DEATH_SELF_VH_CRUSH) \
// 0 = no, 1 = yes, 2 = forced on for all MSG_INFO notifs
// DISABLED IN CODE, BUT ENABLED IN CONFIG FOR COMPATIBILITY WITH OLD CLIENTS
- var float autocvar_notification_allow_chatboxprint = 0;
+ var float autocvar_notification_allow_chatboxprint = 0;
var float autocvar_notification_show_sprees_center = TRUE;
var float autocvar_notification_show_sprees_center_specialonly = TRUE;
allows for more dynamic data to be inferred by the local
notification parser, so that the server does not have to network
anything too crazy on a per-client/per-situation basis.
-
+
Pay attention to the CSQC/SVQC relations, some of these are redefined
in slightly different ways for different programs, this is because the
server does a more conservative approach to the notifs than the client.
-
+
All arguments are swapped into strings, so be sure that your
sprintf usage matches with proper %s placement.
-
+
Argument descriptions:
s1-s4: string arguments to be literally swapped into sprintf
s2loc: s2 string of locations of deaths or other events
ARG_CASE(ARG_CS, "f1secs", count_seconds(f1)) \
ARG_CASE(ARG_CS_SV, "f1ord", count_ordinal(f1)) \
ARG_CASE(ARG_CS, "f1time", process_time(2, f1)) \
- ARG_CASE(ARG_CS_SV, "f1race_time", mmssss(f1)) \
- ARG_CASE(ARG_CS_SV, "f2race_time", mmssss(f2)) \
- ARG_CASE(ARG_CS_SV, "f3race_time", mmssss(f3)) \
+ ARG_CASE(ARG_CS_SV_HA, "f1race_time", mmssss(f1)) \
+ ARG_CASE(ARG_CS_SV_HA, "f2race_time", mmssss(f2)) \
+ ARG_CASE(ARG_CS_SV_HA, "f3race_time", mmssss(f3)) \
ARG_CASE(ARG_CS_SV, "race_col", CCR(((f1 == 1) ? "^F1" : "^F2"))) \
ARG_CASE(ARG_CS_SV, "race_diff", ((f2 > f3) ? sprintf(CCR("^1[+%s]"), mmssss(f2 - f3)) : sprintf(CCR("^2[-%s]"), mmssss(f3 - f2)))) \
ARG_CASE(ARG_CS, "missing_teams", notif_arg_missing_teams(f1, f2, f3, f4)) \
string notif_arg_frag_stats(float fhealth, float farmor, float fping)
{
- if not(fhealth < 1)
+ if (!(fhealth < 1))
return sprintf(CCR(_("\n(Health ^1%d^BG / Armor ^2%d^BG)%s")), fhealth, farmor, notif_arg_frag_ping(FALSE, fping));
else
return sprintf(CCR(_("\n(^F4Dead^BG)%s")), notif_arg_frag_ping(FALSE, fping));
string notif_arg_spree_cen(float spree)
{
// 0 = off, 1 = target (but only for first victim) and attacker
- if(autocvar_notification_show_sprees_center)
+ if(autocvar_notification_show_sprees_center)
{
if(spree > 1)
{
#define SPREE_ITEM(counta,countb,center,normal,gentle) \
case counta: { return normal_or_gentle(center, sprintf(_("%d score spree! "), spree)); }
-
+
switch(spree)
{
KILL_SPREE_LIST
default:
{
- if not(autocvar_notification_show_sprees_center_specialonly)
+ if (!autocvar_notification_show_sprees_center_specialonly)
{
return
sprintf(
),
spree);
}
- else { return ""; } // don't show spree information if it isn't an achievement
+ else { return ""; } // don't show spree information if it isn't an achievement
}
}
{
// 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker
// this conditional (& 2) is true for 2 and 3
- if(autocvar_notification_show_sprees_info & 2)
+ if(autocvar_notification_show_sprees_info & 2)
{
#ifdef CSQC
string spree_newline =
string spree_newline =
(autocvar_notification_show_sprees_info_newline ? "\n" : "");
#endif
-
+
if(spree > 1)
{
#define SPREE_ITEM(counta,countb,center,normal,gentle) \
case counta: { return sprintf(CCR(normal_or_gentle(normal, gentle)), player, spree_newline); }
-
+
switch(spree)
{
KILL_SPREE_LIST
default:
{
- if not(autocvar_notification_show_sprees_info_specialonly)
+ if (!autocvar_notification_show_sprees_info_specialonly)
{
return
sprintf(
spree_newline
);
}
- else { return ""; } // don't show spree information if it isn't an achievement
+ else { return ""; } // don't show spree information if it isn't an achievement
}
}
#else
#define dedi ""
#endif
-
- print(sprintf("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME));
-
+
+ printf("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME);
+
// maybe do another implementation of this with checksums? for now, we don't need versioning
/*if(autocvar_notification_version != NOTIF_VERSION)
{
#endif
notif_global_error = TRUE;
- print(sprintf("^1NOTIFICATION VERSION MISMATCH: ^7program = %s, config = %d, code = %d.\n",
- PROGNAME, autocvar_notification_version, NOTIF_VERSION));
+ printf("^1NOTIFICATION VERSION MISMATCH: ^7program = %s, config = %d, code = %d.\n",
+ PROGNAME, autocvar_notification_version, NOTIF_VERSION);
}*/
}
--- /dev/null
-
+/**
+ turret_checkpoint
+**/
+
+
+//.entity checkpoint_target;
+
+/*
+#define checkpoint_cache_who flagcarried
+#define checkpoint_cache_from lastrocket
+#define checkpoint_cache_to selected_player
+*/
+
+.entity pathgoal;
+
+/*
+entity path_makeorcache(entity forwho,entity start, entity end)
+{
+ entity oldself;
+ entity pth;
+ oldself = self;
+ self = forwho;
+
+ //pth = pathlib_makepath(start.origin,end.origin,PFL_GROUNDSNAP,500,1.5,PT_QUICKSTAR);
+
+ self = oldself;
+ return pth;
+}
+*/
+
+void turret_checkpoint_use()
+{
+}
+
+#if 0
+void turret_checkpoint_think()
+{
+ if(self.enemy)
+ te_lightning1(self,self.origin, self.enemy.origin);
- self.nextthink = time + 0.2;
++
+ self.nextthink = time + 0.25;
+}
+#endif
+/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
+-----------KEYS------------
+target: .targetname of next waypoint in chain.
+wait: Pause at this point # seconds.
+-----------SPAWNFLAGS-----------
+---------NOTES----------
+If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
+If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+*/
+//float tc_acum;
+void turret_checkpoint_init()
+{
+ traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self);
+ setorigin(self, trace_endpos + '0 0 32');
+
+ if(self.target != "")
+ {
+ self.enemy = find(world, targetname, self.target);
+ if(self.enemy == world)
+ dprint("A turret_checkpoint faild to find its target!\n");
+ }
+ //self.think = turret_checkpoint_think;
+ //self.nextthink = time + tc_acum + 0.25;
+ //tc_acum += 0.25;
+}
+
+void spawnfunc_turret_checkpoint()
+{
+ setorigin(self,self.origin);
+ self.think = turret_checkpoint_init;
++ self.nextthink = time + 0.2;
+}
+
+// Compat.
+void spawnfunc_walker_checkpoint()
+{
+ self.classname = "turret_checkpoint";
+ spawnfunc_turret_checkpoint();
+}
--- /dev/null
- switch(hud)
- {
- case HUD_SPIDERBOT:
- case HUD_WAKIZASHI:
- case HUD_RAPTOR:
- case HUD_BUMBLEBEE:
- if((get_turretinfo(self.turretid)).spawnflags & TUR_FLAG_MOVE)
- txt = "gfx/vehicles/vth-mover.tga";
- else
- txt = "gfx/vehicles/vth-stationary.tga";
-
- vector pz = drawgetimagesize(txt) * 0.25;
- drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
- break;
- }
+void turret_remove()
+{
+ remove(self.tur_head);
+ //remove(self.enemy);
+ self.tur_head = world;
+}
+
+.vector glowmod;
+void turret_changeteam()
+{
+ switch(self.team - 1)
+ {
+ case NUM_TEAM_1: // Red
+ self.glowmod = '2 0 0';
+ self.teamradar_color = '1 0 0';
+ break;
+
+ case NUM_TEAM_2: // Blue
+ self.glowmod = '0 0 2';
+ self.teamradar_color = '0 0 1';
+ break;
+
+ case NUM_TEAM_3: // Yellow
+ self.glowmod = '1 1 0';
+ self.teamradar_color = '1 1 0';
+ break;
+
+ case NUM_TEAM_4: // Pink
+ self.glowmod = '1 0 1';
+ self.teamradar_color = '1 0 1';
+ break;
+ }
+
+ if(self.team)
+ self.colormap = 1024 + (self.team - 1) * 17;
+
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
+
+}
+
+void turret_head_draw()
+{
+ self.drawmask = MASK_NORMAL;
+}
+
+void turret_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+
+ if (self.health < 127)
+ {
+ dt = random();
+
+ if(dt < 0.03)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+ }
+
+ if(self.health < 85)
+ if(dt < 0.01)
+ pointparticles(particleeffectnum("smoke_large"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+
+ if(self.health < 32)
+ if(dt < 0.015)
+ pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+
+}
+
+void turret_draw2d()
+{
+ if(self.netname == "")
+ return;
+
+ if(!autocvar_g_waypointsprite_turrets)
+ return;
+
+ if(autocvar_cl_hidewaypoints)
+ return;
+
+ float dist = vlen(self.origin - view_origin);
+ float t = (GetPlayerColor(player_localnum) + 1);
+
+ vector o;
+ string txt;
+
+ if(autocvar_cl_vehicles_hud_tactical)
+ if(dist < 10240 && t != self.team)
+ {
+ // TODO: Vehicle tactical hud
+ o = project_3d_to_2d(self.origin + '0 0 32');
+ if(o_z < 0
+ || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
+ || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
+ || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
+ || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+ return; // Dont draw wp's for turrets out of view
+ o_z = 0;
+ if(hud != HUD_NORMAL)
+ {
- print(sprintf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage));
++ if((get_turretinfo(self.turretid)).spawnflags & TUR_FLAG_MOVE)
++ txt = "gfx/vehicles/vth-mover.tga";
++ else
++ txt = "gfx/vehicles/vth-stationary.tga";
++
++ vector pz = drawgetimagesize(txt) * 0.25;
++ drawpic(o - pz * 0.5, txt, pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
+ }
+ }
+
+ if(dist > self.maxdistance)
+ return;
+
+ string spriteimage = self.netname;
+ float a = self.alpha * autocvar_hud_panel_fg_alpha;
+ vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+
+
+ if(self.maxdistance > waypointsprite_normdistance)
+ a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
+ else if(self.maxdistance > 0)
+ a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
+
+ if(rgb == '0 0 0')
+ {
+ self.teamradar_color = '1 0 1';
++ printf("WARNING: sprite of name %s has no color, using pink so you notice it\n", spriteimage);
+ }
+
+ txt = self.netname;
+ if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
+ txt = _("Spam");
+ else
+ txt = spritelookuptext(spriteimage);
+
+ if(time - floor(time) > 0.5 && t == self.team)
+ {
+ if(self.helpme && time < self.helpme)
+ {
+ a *= SPRITE_HELPME_BLINK;
+ txt = sprintf(_("%s under attack!"), txt);
+ }
+ else
+ a *= spritelookupblinkvalue(spriteimage);
+ }
+
+ if(autocvar_g_waypointsprite_uppercase)
+ txt = strtoupper(txt);
+
+ if(a > 1)
+ {
+ rgb *= a;
+ a = 1;
+ }
+
+ if(a <= 0)
+ return;
+
+ rgb = fixrgbexcess(rgb);
+
+ o = project_3d_to_2d(self.origin + '0 0 64');
+ if(o_z < 0
+ || o_x < (vid_conwidth * waypointsprite_edgeoffset_left)
+ || o_y < (vid_conheight * waypointsprite_edgeoffset_top)
+ || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))
+ || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
+ return; // Dont draw wp's for turrets out of view
+
+ o_z = 0;
+
+ float edgedistance_min, crosshairdistance;
+ edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)),
+ (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)),
+ (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x,
+ (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y);
+
+ float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
+
+ crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
+
+ t = waypointsprite_scale * vidscale;
+ a *= waypointsprite_alpha;
+
+ {
+ a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
+ }
+ if (edgedistance_min < waypointsprite_edgefadedistance) {
+ a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
+ }
+ if(crosshairdistance < waypointsprite_crosshairfadedistance) {
+ a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+ t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
+ }
+
+ o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
+ o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+ drawhealthbar(
+ o,
+ 0,
+ self.health / 255,
+ '0 0 0',
+ '0 0 0',
+ 0.5 * SPRITE_HEALTHBAR_WIDTH * t,
+ 0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
+ SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
+ SPRITE_HEALTHBAR_BORDER * t,
+ 0,
+ rgb,
+ a * SPRITE_HEALTHBAR_BORDERALPHA,
+ rgb,
+ a * SPRITE_HEALTHBAR_HEALTHALPHA,
+ DRAWFLAG_NORMAL
+ );
+}
+
+void(entity e, entity tagentity, string tagname) setattachment = #443;
+void turret_construct()
+{
+ entity tur = get_turretinfo(self.turretid);
+
+ if(self.tur_head == world)
+ self.tur_head = spawn();
+
+ self.netname = TUR_NAME(self.turretid);
+
+ setorigin(self, self.origin);
+ setmodel(self, tur.model);
+ setmodel(self.tur_head, tur.head_model);
+ setsize(self, tur.mins, tur.maxs);
+ setsize(self.tur_head, '0 0 0', '0 0 0');
+
+ if(self.turretid == TUR_EWHEEL)
+ setattachment(self.tur_head, self, "");
+ else
+ setattachment(self.tur_head, self, "tag_head");
+
+ self.tur_head.classname = "turret_head";
+ self.tur_head.owner = self;
+ self.tur_head.move_movetype = MOVETYPE_NOCLIP;
+ self.move_movetype = MOVETYPE_NOCLIP;
+ self.tur_head.angles = self.angles;
+ self.health = 255;
+ self.solid = SOLID_BBOX;
+ self.tur_head.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.tur_head.movetype = MOVETYPE_NOCLIP;
+ self.draw = turret_draw;
+ self.entremove = turret_remove;
+ self.drawmask = MASK_NORMAL;
+ self.tur_head.drawmask = MASK_NORMAL;
+ self.anim_start_time = 0;
+ self.draw2d = turret_draw2d;
+ self.maxdistance = autocvar_g_waypointsprite_turrets_maxdist;
+ self.teamradar_color = '1 0 0';
+ self.alpha = 1;
+
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
+void turret_gibboom();
+void turret_gib_draw()
+{
+ Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+
+ self.drawmask = MASK_NORMAL;
+
+ if(self.cnt)
+ {
+ if(time >= self.nextthink)
+ {
+ turret_gibboom();
+ remove(self);
+ }
+ }
+ else
+ {
+ self.alpha = bound(0, self.nextthink - time, 1);
+ if(self.alpha < ALPHA_MIN_VISIBLE)
+ remove(self);
+ }
+}
+
+void turret_gibboom()
+{
+ float i;
+
+ sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+ for (i = 1; i < 5; i = i + 1)
+ turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', FALSE);
+}
+
+entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode)
+{
+ entity gib;
+
+ traceline(_from, _to, MOVE_NOMONSTERS, world);
+ if(trace_startsolid)
+ return world;
+
+ gib = spawn();
+ setorigin(gib, _from);
+ setmodel(gib, _model);
+ gib.colormod = _cmod;
+ gib.solid = SOLID_CORPSE;
+ gib.draw = turret_gib_draw;
+ gib.cnt = _explode;
+ setsize(gib, '-1 -1 -1', '1 1 1');
+ if(_explode)
+ {
+ gib.nextthink = time + 0.2 * (autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15));
+ gib.effects = EF_FLAME;
+ }
+ else
+ gib.nextthink = time + autocvar_cl_gibs_lifetime * (1 + prandom() * 0.15);
+
+ gib.gravity = 1;
+ gib.move_movetype = MOVETYPE_BOUNCE;
+ gib.move_origin = _from;
+ setorigin(gib, _from);
+ gib.move_velocity = _to;
+ gib.move_avelocity = prandomvec() * 32;
+ gib.move_time = time;
+ gib.damageforcescale = 1;
+ gib.classname = "turret_gib";
+
+ return gib;
+}
+
+void turret_die()
+{
+ sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ if (!autocvar_cl_nogibs)
+ {
+ // Base
+ if(self.turretid == TUR_EWHEEL)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', TRUE);
+ else if (self.turretid == TUR_WALKER)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', TRUE);
+ else if (self.turretid == TUR_TESLA)
+ turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', FALSE);
+ else
+ {
+ if (random() > 0.5)
+ {
+ turret_gibtoss("models/turrets/base-gib2.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+ turret_gibtoss("models/turrets/base-gib3.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+ turret_gibtoss("models/turrets/base-gib4.md3", self.origin + '0 0 8', '0 0 50' + randomvec() * 150, '0 0 0', FALSE);
+ }
+ else
+ turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', TRUE);
+
+ entity headgib = turret_gibtoss((get_turretinfo(self.turretid)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', TRUE);
+ if(headgib)
+ {
+ headgib.angles = headgib.move_angles = self.tur_head.angles;
+ headgib.avelocity = headgib.move_avelocity = self.tur_head.move_avelocity + randomvec() * 45;
+ headgib.avelocity_y = headgib.move_avelocity_y = headgib.move_avelocity_y * 5;
+ headgib.gravity = 0.5;
+ }
+ }
+ }
+
+ setmodel(self, "null");
+ setmodel(self.tur_head, "null");
+}
+
+void ent_turret()
+{
+ float sf;
+ sf = ReadByte();
+
+ if(sf & TNSF_SETUP)
+ {
+ self.turretid = ReadByte();
+
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
+
+ self.angles_x = ReadAngle();
+ self.angles_y = ReadAngle();
+
+ turret_construct();
+ self.colormap = 1024;
+ self.glowmod = '0 1 1';
+ self.tur_head.colormap = self.colormap;
+ self.tur_head.glowmod = self.glowmod;
+ }
+
+ if(sf & TNSF_ANG)
+ {
+ if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
+ self.tur_head = spawn();
+
+ self.tur_head.move_angles_x = ReadShort();
+ self.tur_head.move_angles_y = ReadShort();
+ //self.tur_head.angles = self.angles + self.tur_head.move_angles;
+ self.tur_head.angles = self.tur_head.move_angles;
+ }
+
+ if(sf & TNSF_AVEL)
+ {
+ if(self.tur_head == world) // aparenly this can happpen before TNSF_SETUP. great.
+ self.tur_head = spawn();
+
+ self.tur_head.move_avelocity_x = ReadShort();
+ self.tur_head.move_avelocity_y = ReadShort();
+ }
+
+ if(sf & TNSF_MOVE)
+ {
+ self.origin_x = ReadShort();
+ self.origin_y = ReadShort();
+ self.origin_z = ReadShort();
+ setorigin(self, self.origin);
+
+ self.velocity_x = ReadShort();
+ self.velocity_y = ReadShort();
+ self.velocity_z = ReadShort();
+
+ self.move_angles_y = ReadShort();
+
+ self.move_time = time;
+ self.move_velocity = self.velocity;
+ self.move_origin = self.origin;
+ }
+
+ if(sf & TNSF_ANIM)
+ {
+ self.frame1time = ReadCoord();
+ self.frame = ReadByte();
+ }
+
+ if(sf & TNSF_STATUS)
+ {
+ float _tmp;
+ _tmp = ReadByte();
+ if(_tmp != self.team)
+ {
+ self.team = _tmp;
+ turret_changeteam();
+ }
+
+ _tmp = ReadByte();
+ if(_tmp == 0 && self.health != 0)
+ turret_die();
+ else if(self.health && self.health != _tmp)
+ self.helpme = servertime + 10;
+
+ self.health = _tmp;
+ }
+ //self.enemy.health = self.health / 255;
+}
--- /dev/null
- // FIXME: this cant be the best way to do this..
+// =========================
+// SVQC Turret Properties
+// =========================
+
+
+// Generic aiming
+vector turret_aim_generic()
+{
+
+ vector pre_pos, prep;
+ float distance, impact_time = 0, i, mintime;
+
+ turret_tag_fire_update();
+
+ if(self.aim_flags & TFL_AIM_SIMPLE)
+ return real_origin(self.enemy);
+
+ mintime = max(self.attack_finished_single - time,0) + sys_frametime;
+
+ // Baseline
+ pre_pos = real_origin(self.enemy);
+
+ // Lead?
+ if (self.aim_flags & TFL_AIM_LEAD)
+ {
+ if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
+ {
-
- for(i = 0; i < 4; ++i)
- {
- distance = vlen(prep - self.tur_shotorg);
- impact_time = distance / self.shot_speed;
- prep = pre_pos + self.enemy.velocity * impact_time;
- }
+ prep = pre_pos;
- if not(self.enemy.flags & FL_ONGROUND)
++
++ distance = vlen(prep - self.tur_shotorg);
++ impact_time = distance / self.shot_speed;
+
+ prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
+
+ if(self.aim_flags & TFL_AIM_ZPREDICT)
- if not (self.active)
++ if(!(self.enemy.flags & FL_ONGROUND))
+ if(self.enemy.movetype == MOVETYPE_WALK || self.enemy.movetype == MOVETYPE_TOSS || self.enemy.movetype == MOVETYPE_BOUNCE)
+ {
+ float vz;
+ prep_z = pre_pos_z;
+ vz = self.enemy.velocity_z;
+ for(i = 0; i < impact_time; i += sys_frametime)
+ {
+ vz = vz - (autocvar_sv_gravity * sys_frametime);
+ prep_z = prep_z + vz * sys_frametime;
+ }
+ }
+ pre_pos = prep;
+ }
+ else
+ pre_pos = pre_pos + self.enemy.velocity * mintime;
+ }
+
+ if(self.aim_flags & TFL_AIM_SPLASH)
+ {
+ //tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
+ traceline(pre_pos + '0 0 32',pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
+ if(trace_fraction != 1.0)
+ pre_pos = trace_endpos;
+ }
+
+ return pre_pos;
+}
+
+float turret_targetscore_support(entity _turret,entity _target)
+{
+ float score; // Total score
+ float s_score = 0, d_score;
+
+ if (_turret.enemy == _target) s_score = 1;
+
+ d_score = min(_turret.target_range_optimal,tvt_dist) / max(_turret.target_range_optimal,tvt_dist);
+
+ score = (d_score * _turret.target_select_rangebias) +
+ (s_score * _turret.target_select_samebias);
+
+ return score;
+}
+
+/*
+* Generic bias aware score system.
+*/
+float turret_targetscore_generic(entity _turret, entity _target)
+{
+ float d_dist; // Defendmode Distance
+ float score; // Total score
+ float d_score; // Distance score
+ float a_score; // Angular score
+ float m_score = 0; // missile score
+ float p_score = 0; // player score
+ float ikr; // ideal kill range
+
+ if (_turret.tur_defend)
+ {
+ d_dist = vlen(real_origin(_target) - _turret.tur_defend.origin);
+ ikr = vlen(_turret.origin - _turret.tur_defend.origin);
+ d_score = 1 - d_dist / _turret.target_range;
+ }
+ else
+ {
+ // Make a normlized value base on the targets distance from our optimal killzone
+ ikr = _turret.target_range_optimal;
+ d_score = min(ikr, tvt_dist) / max(ikr, tvt_dist);
+ }
+
+ a_score = 1 - tvt_thadf / _turret.aim_maxrotate;
+
+ if ((_turret.target_select_missilebias > 0) && (_target.flags & FL_PROJECTILE))
+ m_score = 1;
+
+ if ((_turret.target_select_playerbias > 0) && IS_CLIENT(_target))
+ p_score = 1;
+
+ d_score = max(d_score, 0);
+ a_score = max(a_score, 0);
+ m_score = max(m_score, 0);
+ p_score = max(p_score, 0);
+
+ score = (d_score * _turret.target_select_rangebias) +
+ (a_score * _turret.target_select_anglebias) +
+ (m_score * _turret.target_select_missilebias) +
+ (p_score * _turret.target_select_playerbias);
+
+ if(_turret.target_range < vlen(_turret.tur_shotorg - real_origin(_target)))
+ {
+ //dprint("Wtf?\n");
+ score *= 0.001;
+ }
+
+#ifdef TURRET_DEBUG
+ string sd,sa,sm,sp,ss;
+ string sdt,sat,smt,spt;
+
+ sd = ftos(d_score);
+ d_score *= _turret.target_select_rangebias;
+ sdt = ftos(d_score);
+
+ //sv = ftos(v_score);
+ //v_score *= _turret.target_select_samebias;
+ //svt = ftos(v_score);
+
+ sa = ftos(a_score);
+ a_score *= _turret.target_select_anglebias;
+ sat = ftos(a_score);
+
+ sm = ftos(m_score);
+ m_score *= _turret.target_select_missilebias;
+ smt = ftos(m_score);
+
+ sp = ftos(p_score);
+ p_score *= _turret.target_select_playerbias;
+ spt = ftos(p_score);
+
+
+ ss = ftos(score);
+ bprint("^3Target scores^7 \[ ",_turret.netname, " \] ^3for^7 \[ ", _target.netname," \]\n");
+ bprint("^5Range:\[ ",sd, " \]^2+bias:\[ ",sdt," \]\n");
+ bprint("^5Angle:\[ ",sa, " \]^2+bias:\[ ",sat," \]\n");
+ bprint("^5Missile:\[ ",sm," \]^2+bias:\[ ",smt," \]\n");
+ bprint("^5Player:\[ ",sp, " \]^2+bias:\[ ",spt," \]\n");
+ bprint("^3Total (w/bias):\[^1",ss,"\]\n");
+
+#endif
+
+ return score;
+}
+
+// Generic damage handling
+void() turret_respawn;
+void turret_hide()
+{
+ self.effects |= EF_NODRAW;
+ self.nextthink = time + self.respawntime - 0.2;
+ self.think = turret_respawn;
+}
+
+void turret_die()
+{
+ self.deadflag = DEAD_DEAD;
+ self.tur_head.deadflag = self.deadflag;
+
+// Unsolidify and hide real parts
+ self.solid = SOLID_NOT;
+ self.tur_head.solid = self.solid;
+
+ self.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+
+ self.health = 0;
+
+// Go boom
+ //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
+
+ if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
+ {
+ TUR_ACTION(self.turretid, TR_DEATH);
+
+ remove(self.tur_head);
+ remove(self);
+ }
+ else
+ {
+ // Setup respawn
+ self.SendFlags |= TNSF_STATUS;
+ self.nextthink = time + 0.2;
+ self.think = turret_hide;
+
+ TUR_ACTION(self.turretid, TR_DEATH);
+ }
+}
+
+void turret_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+ // Enougth allready!
+ if(self.deadflag == DEAD_DEAD)
+ return;
+
+ // Inactive turrets take no damage. (hm..)
- if not (ent.turret_scale_damage) ent.turret_scale_damage = 1;
- if not (ent.turret_scale_range) ent.turret_scale_range = 1;
- if not (ent.turret_scale_refire) ent.turret_scale_refire = 1;
- if not (ent.turret_scale_ammo) ent.turret_scale_ammo = 1;
- if not (ent.turret_scale_aim) ent.turret_scale_aim = 1;
- if not (ent.turret_scale_health) ent.turret_scale_health = 1;
- if not (ent.turret_scale_respawn) ent.turret_scale_respawn = 1;
++ if(!self.active)
+ return;
+
+ if (teamplay)
+ if (self.team == attacker.team)
+ {
+ // This does not happen anymore. Re-enable if you fix that.
+ if(IS_REAL_CLIENT(attacker))
+ sprint(attacker, "\{1}Turret tells you: I'm on your team!\n");
+
+ if(autocvar_g_friendlyfire)
+ damage = damage * autocvar_g_friendlyfire;
+ else
+ return;
+ }
+
+ self.health -= damage;
+
+ // thorw head slightly off aim when hit?
+ if (self.damage_flags & TFL_DMG_HEADSHAKE)
+ {
+ self.tur_head.angles_x = self.tur_head.angles_x + (-0.5 + random()) * damage;
+ self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if (self.turret_flags & TUR_FLAG_MOVE)
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ {
+ self.event_damage = func_null;
+ self.tur_head.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+ self.nextthink = time;
+ self.think = turret_die;
+ }
+
+ self.SendFlags |= TNSF_STATUS;
+}
+
+void() turret_think;
+void turret_respawn()
+{
+ // Make sure all parts belong to the same team since
+ // this function doubles as "teamchange" function.
+ self.tur_head.team = self.team;
+ self.effects &= ~EF_NODRAW;
+ self.deadflag = DEAD_NO;
+ self.effects = EF_LOWPRECISION;
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.event_damage = turret_damage;
+ self.avelocity = '0 0 0';
+ self.tur_head.avelocity = self.avelocity;
+ self.tur_head.angles = self.idle_aim;
+ self.health = self.max_health;
+ self.enemy = world;
+ self.volly_counter = self.shot_volly;
+ self.ammo = self.ammo_max;
+
+ self.nextthink = time + self.ticrate;
+ self.think = turret_think;
+
+ self.SendFlags = TNSF_FULL_UPDATE;
+
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+
+// Main functions
+#define cvar_base "g_turrets_unit_"
+.float clientframe;
+void turrets_setframe(float _frame, float client_only)
+{
+ if((client_only ? self.clientframe : self.frame ) != _frame)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ if(client_only)
+ self.clientframe = _frame;
+ else
+ self.frame = _frame;
+
+}
+
+float turret_send(entity to, float sf)
+{
+
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & TNSF_SETUP)
+ {
+ WriteByte(MSG_ENTITY, self.turretid);
+
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+
+ WriteAngle(MSG_ENTITY, self.angles_x);
+ WriteAngle(MSG_ENTITY, self.angles_y);
+ }
+
+ if(sf & TNSF_ANG)
+ {
+ WriteShort(MSG_ENTITY, rint(self.tur_head.angles_x));
+ WriteShort(MSG_ENTITY, rint(self.tur_head.angles_y));
+ }
+
+ if(sf & TNSF_AVEL)
+ {
+ WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_x));
+ WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_y));
+ }
+
+ if(sf & TNSF_MOVE)
+ {
+ WriteShort(MSG_ENTITY, rint(self.origin_x));
+ WriteShort(MSG_ENTITY, rint(self.origin_y));
+ WriteShort(MSG_ENTITY, rint(self.origin_z));
+
+ WriteShort(MSG_ENTITY, rint(self.velocity_x));
+ WriteShort(MSG_ENTITY, rint(self.velocity_y));
+ WriteShort(MSG_ENTITY, rint(self.velocity_z));
+
+ WriteShort(MSG_ENTITY, rint(self.angles_y));
+ }
+
+ if(sf & TNSF_ANIM)
+ {
+ WriteCoord(MSG_ENTITY, self.anim_start_time);
+ WriteByte(MSG_ENTITY, self.frame);
+ }
+
+ if(sf & TNSF_STATUS)
+ {
+ WriteByte(MSG_ENTITY, self.team);
+
+ if(self.health <= 0)
+ WriteByte(MSG_ENTITY, 0);
+ else
+ WriteByte(MSG_ENTITY, ceil((self.health / self.max_health) * 255));
+ }
+
+ return TRUE;
+}
+
+void load_unit_settings(entity ent, string unitname, float is_reload)
+{
+ string sbase;
+
+ if (ent == world)
+ return;
+
- if not (self.active)
++ if(!ent.turret_scale_damage) ent.turret_scale_damage = 1;
++ if(!ent.turret_scale_range) ent.turret_scale_range = 1;
++ if(!ent.turret_scale_refire) ent.turret_scale_refire = 1;
++ if(!ent.turret_scale_ammo) ent.turret_scale_ammo = 1;
++ if(!ent.turret_scale_aim) ent.turret_scale_aim = 1;
++ if(!ent.turret_scale_health) ent.turret_scale_health = 1;
++ if(!ent.turret_scale_respawn) ent.turret_scale_respawn = 1;
+
+ sbase = strcat(cvar_base,unitname);
+ if (is_reload)
+ {
+ ent.enemy = world;
+ ent.tur_head.avelocity = '0 0 0';
+
+ ent.tur_head.angles = '0 0 0';
+ }
+
+ ent.health = cvar(strcat(sbase,"_health")) * ent.turret_scale_health;
+ ent.respawntime = cvar(strcat(sbase,"_respawntime")) * ent.turret_scale_respawn;
+
+ ent.shot_dmg = cvar(strcat(sbase,"_shot_dmg")) * ent.turret_scale_damage;
+ ent.shot_refire = cvar(strcat(sbase,"_shot_refire")) * ent.turret_scale_refire;
+ ent.shot_radius = cvar(strcat(sbase,"_shot_radius")) * ent.turret_scale_damage;
+ ent.shot_speed = cvar(strcat(sbase,"_shot_speed"));
+ ent.shot_spread = cvar(strcat(sbase,"_shot_spread"));
+ ent.shot_force = cvar(strcat(sbase,"_shot_force")) * ent.turret_scale_damage;
+ ent.shot_volly = cvar(strcat(sbase,"_shot_volly"));
+ ent.shot_volly_refire = cvar(strcat(sbase,"_shot_volly_refire")) * ent.turret_scale_refire;
+
+ ent.target_range = cvar(strcat(sbase,"_target_range")) * ent.turret_scale_range;
+ ent.target_range_min = cvar(strcat(sbase,"_target_range_min")) * ent.turret_scale_range;
+ ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * ent.turret_scale_range;
+ //ent.target_range_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
+
+ ent.target_select_rangebias = cvar(strcat(sbase,"_target_select_rangebias"));
+ ent.target_select_samebias = cvar(strcat(sbase,"_target_select_samebias"));
+ ent.target_select_anglebias = cvar(strcat(sbase,"_target_select_anglebias"));
+ ent.target_select_playerbias = cvar(strcat(sbase,"_target_select_playerbias"));
+ //ent.target_select_fov = cvar(cvar_gets(sbase,"_target_select_fov"));
+
+ ent.ammo_max = cvar(strcat(sbase,"_ammo_max")) * ent.turret_scale_ammo;
+ ent.ammo_recharge = cvar(strcat(sbase,"_ammo_recharge")) * ent.turret_scale_ammo;
+
+ ent.aim_firetolerance_dist = cvar(strcat(sbase,"_aim_firetolerance_dist"));
+ ent.aim_speed = cvar(strcat(sbase,"_aim_speed")) * ent.turret_scale_aim;
+ ent.aim_maxrotate = cvar(strcat(sbase,"_aim_maxrot"));
+ ent.aim_maxpitch = cvar(strcat(sbase,"_aim_maxpitch"));
+
+ ent.track_type = cvar(strcat(sbase,"_track_type"));
+ ent.track_accel_pitch = cvar(strcat(sbase,"_track_accel_pitch"));
+ ent.track_accel_rotate = cvar(strcat(sbase,"_track_accel_rot"));
+ ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
+
+ if(is_reload)
+ TUR_ACTION(self.turretid, TR_SETUP);
+}
+
+void turret_projectile_explode()
+{
+
+ self.takedamage = DAMAGE_NO;
+ self.event_damage = func_null;
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_debug_dmg_t_h = self.owner.tur_debug_dmg_t_h + d;
+ self.owner.tur_debug_dmg_t_f = self.owner.tur_debug_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
+void turret_projectile_touch()
+{
+ PROJECTILE_TOUCH;
+ turret_projectile_explode();
+}
+
+void turret_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+ self.velocity += vforce;
+ self.health -= damage;
+ //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
+ if(self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, turret_projectile_explode);
+}
+
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
+{
+ entity proj;
+
+ sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
+ proj.owner = self;
+ proj.realowner = self;
+ proj.bot_dodge = TRUE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_projectile_explode;
+ proj.touch = turret_projectile_touch;
+ proj.nextthink = time + 9;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ proj.flags = FL_PROJECTILE;
+ proj.enemy = self.enemy;
+ proj.totalfrags = _death;
+ PROJECTILE_MAKETRIGGER(proj);
+ if(_health)
+ {
+ proj.health = _health;
+ proj.takedamage = DAMAGE_YES;
+ proj.event_damage = turret_projectile_damage;
+ }
+ else
+ proj.flags |= FL_NOTARGET;
+
+ CSQCProjectile(proj, _cli_anim, _proj_type, _cull);
+
+ return proj;
+}
+
+/**
+** updates enemy distances, predicted impact point/time
+** and updated aim<->predict impact distance.
+**/
+void turret_do_updates(entity t_turret)
+{
+ vector enemy_pos;
+ entity oldself;
+
+ oldself = self;
+ self = t_turret;
+
+ enemy_pos = real_origin(self.enemy);
+
+ turret_tag_fire_update();
+
+ self.tur_shotdir_updated = v_forward;
+ self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos);
+ self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos);
+
+ /*if((self.firecheck_flags & TFL_FIRECHECK_VERIFIED) && (self.enemy))
+ {
+ oldpos = self.enemy.origin;
+ setorigin(self.enemy, self.tur_aimpos);
+ tracebox(self.tur_shotorg, '-1 -1 -1', '1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
+ setorigin(self.enemy, oldpos);
+
+ if(trace_ent == self.enemy)
+ self.tur_dist_impact_to_aimpos = 0;
+ else
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
+ }
+ else*/
+ tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos), MOVE_NORMAL,self);
+
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5);
+ self.tur_impactent = trace_ent;
+ self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
+
+ self = oldself;
+}
+
+/**
+** Handles head rotation according to
+** the units .track_type and .track_flags
+**/
+.float turret_framecounter;
+void turret_track()
+{
+ vector target_angle; // This is where we want to aim
+ vector move_angle; // This is where we can aim
+ float f_tmp;
+ vector v1, v2;
+ v1 = self.tur_head.angles;
+ v2 = self.tur_head.avelocity;
+
+ if (self.track_flags == TFL_TRACK_NO)
+ return;
+
- if not(checkpvs(e_target.origin, e_turret))
++ if(!self.active)
+ target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
+ else if (self.enemy == world)
+ {
+ if(time > self.lip)
+ target_angle = self.idle_aim + self.angles;
+ else
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
+ }
+ else
+ {
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
+ }
+
+ self.tur_head.angles_x = anglemods(self.tur_head.angles_x);
+ self.tur_head.angles_y = anglemods(self.tur_head.angles_y);
+
+ // Find the diffrence between where we currently aim and where we want to aim
+ //move_angle = target_angle - (self.angles + self.tur_head.angles);
+ //move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
+
+ move_angle = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(self.angles), AnglesTransform_FromAngles(target_angle))) - self.tur_head.angles;
+ move_angle = shortangle_vxy(move_angle, self.tur_head.angles);
+
+ switch(self.track_type)
+ {
+ case TFL_TRACKTYPE_STEPMOTOR:
+ f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
+ if (self.track_flags & TFL_TRACK_PITCH)
+ {
+ self.tur_head.angles_x += bound(-f_tmp,move_angle_x, f_tmp);
+ if(self.tur_head.angles_x > self.aim_maxpitch)
+ self.tur_head.angles_x = self.aim_maxpitch;
+
+ if(self.tur_head.angles_x < -self.aim_maxpitch)
+ self.tur_head.angles_x = self.aim_maxpitch;
+ }
+
+ if (self.track_flags & TFL_TRACK_ROTATE)
+ {
+ self.tur_head.angles_y += bound(-f_tmp, move_angle_y, f_tmp);
+ if(self.tur_head.angles_y > self.aim_maxrotate)
+ self.tur_head.angles_y = self.aim_maxrotate;
+
+ if(self.tur_head.angles_y < -self.aim_maxrotate)
+ self.tur_head.angles_y = self.aim_maxrotate;
+ }
+
+ // CSQC
+ self.SendFlags |= TNSF_ANG;
+
+ return;
+
+ case TFL_TRACKTYPE_FLUIDINERTIA:
+ f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
+ move_angle_x = bound(-self.aim_speed, move_angle_x * self.track_accel_pitch * f_tmp, self.aim_speed);
+ move_angle_y = bound(-self.aim_speed, move_angle_y * self.track_accel_rotate * f_tmp, self.aim_speed);
+ move_angle = (self.tur_head.avelocity * self.track_blendrate) + (move_angle * (1 - self.track_blendrate));
+ break;
+
+ case TFL_TRACKTYPE_FLUIDPRECISE:
+
+ move_angle_y = bound(-self.aim_speed, move_angle_y, self.aim_speed);
+ move_angle_x = bound(-self.aim_speed, move_angle_x, self.aim_speed);
+
+ break;
+ }
+
+ // pitch
+ if (self.track_flags & TFL_TRACK_PITCH)
+ {
+ self.tur_head.avelocity_x = move_angle_x;
+ if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) > self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = self.aim_maxpitch;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) < -self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = -self.aim_maxpitch;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+ }
+
+ // rot
+ if (self.track_flags & TFL_TRACK_ROTATE)
+ {
+ self.tur_head.avelocity_y = move_angle_y;
+
+ if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) > self.aim_maxrotate)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = self.aim_maxrotate;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+
+ if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) < -self.aim_maxrotate)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = -self.aim_maxrotate;
+
+ self.SendFlags |= TNSF_ANG;
+ }
+ }
+
+ self.SendFlags |= TNSF_AVEL;
+
+ // Force a angle update every 10'th frame
+ self.turret_framecounter += 1;
+ if(self.turret_framecounter >= 10)
+ {
+ self.SendFlags |= TNSF_ANG;
+ self.turret_framecounter = 0;
+ }
+}
+
+/*
+ + TFL_TARGETSELECT_NO
+ + TFL_TARGETSELECT_LOS
+ + TFL_TARGETSELECT_PLAYERS
+ + TFL_TARGETSELECT_MISSILES
+ - TFL_TARGETSELECT_TRIGGERTARGET
+ + TFL_TARGETSELECT_ANGLELIMITS
+ + TFL_TARGETSELECT_RANGELIMITS
+ + TFL_TARGETSELECT_TEAMCHECK
+ - TFL_TARGETSELECT_NOBUILTIN
+ + TFL_TARGETSELECT_OWNTEAM
+*/
+
+/**
+** Evaluate a entity for target valitity based on validate_flags
+** NOTE: the caller must check takedamage before calling this, to inline this check.
+**/
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
+{
+ vector v_tmp;
+
+ //if(!validate_flags & TFL_TARGETSELECT_NOBUILTIN)
+ // return -0.5;
+
+ if(e_target.owner == e_turret)
+ return -0.5;
+
- if not (e_target)
++ if(!checkpvs(e_target.origin, e_turret))
+ return -1;
+
- if not (validate_flags & TFL_TARGETSELECT_PLAYERS)
++ if(!e_target)
+ return -2;
+
+ if(g_onslaught)
+ if (substring(e_target.classname, 0, 10) == "onslaught_") // don't attack onslaught targets, that's the player's job!
+ return - 3;
+
+ if (validate_flags & TFL_TARGETSELECT_NO)
+ return -4;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return -5;
+
+ // Cant touch this
+ if(e_target.vehicle_flags & VHF_ISVEHICLE)
+ {
+ if (e_target.vehicle_health <= 0)
+ return -6;
+ }
+ else if (e_target.health <= 0)
+ return -6;
++ else if(e_target.freezetag_frozen > 0)
++ return -6;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
- if not (validate_flags & TFL_TARGETSELECT_MISSILES)
- return -10;
++ if(!(validate_flags & TFL_TARGETSELECT_PLAYERS))
+ return -7;
+
+ if (e_target.deadflag != DEAD_NO)
+ return -8;
+ }
+
+ // enemy turrets
+ if(validate_flags & TFL_TARGETSELECT_NOTURRETS)
+ if(e_target.owner.tur_head == e_target)
+ if(e_target.team != e_turret.team) // Dont break support units.
+ return -9;
+
+ // Missile
+ if (e_target.flags & FL_PROJECTILE)
- if not (e_target.flags & FL_PROJECTILE)
- return -10.5;
++ if(!(validate_flags & TFL_TARGETSELECT_MISSILES))
++ return -10;
+
+ if (validate_flags & TFL_TARGETSELECT_MISSILESONLY)
- if not (self.spawnflags & TSF_NO_AMMO_REGEN)
++ if(!(e_target.flags & FL_PROJECTILE))
++ return -10.5;
+
+ // Team check
+ if (validate_flags & TFL_TARGETSELECT_TEAMCHECK)
+ {
+ if (validate_flags & TFL_TARGETSELECT_OWNTEAM)
+ {
+ if (e_target.team != e_turret.team)
+ return -11;
+
+ if (e_turret.team != e_target.owner.team)
+ return -12;
+ }
+ else
+ {
+ if (e_target.team == e_turret.team)
+ return -13;
+
+ if (e_turret.team == e_target.owner.team)
+ return -14;
+ }
+ }
+
+ // Range limits?
+ tvt_dist = vlen(e_turret.origin - real_origin(e_target));
+ if (validate_flags & TFL_TARGETSELECT_RANGELIMITS)
+ {
+ if (tvt_dist < e_turret.target_range_min)
+ return -15;
+
+ if (tvt_dist > e_turret.target_range)
+ return -16;
+ }
+
+ // Can we even aim this thing?
+ tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target);
+ tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
+ tvt_thadf = vlen(tvt_thadv);
+ tvt_tadf = vlen(tvt_tadv);
+
+ /*
+ if(validate_flags & TFL_TARGETSELECT_FOV)
+ {
+ if(e_turret.target_select_fov < tvt_thadf)
+ return -21;
+ }
+ */
+
+ if (validate_flags & TFL_TARGETSELECT_ANGLELIMITS)
+ {
+ if (fabs(tvt_tadv_x) > e_turret.aim_maxpitch)
+ return -17;
+
+ if (fabs(tvt_tadv_y) > e_turret.aim_maxrotate)
+ return -18;
+ }
+
+ // Line of sight?
+ if (validate_flags & TFL_TARGETSELECT_LOS)
+ {
+ v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5);
+
+ traceline(e_turret.origin + '0 0 16', v_tmp, 0, e_turret);
+
+ if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos))
+ return -19;
+ }
+
+ if (e_target.classname == "grapplinghook")
+ return -20;
+
+ /*
+ if (e_target.classname == "func_button")
+ return -21;
+ */
+
+#ifdef TURRET_DEBUG_TARGETSELECT
+ dprint("Target:",e_target.netname," is a valid target for ",e_turret.netname,"\n");
+#endif
+
+ return 1;
+}
+
+entity turret_select_target()
+{
+ entity e; // target looper entity
+ float score; // target looper entity score
+ entity e_enemy; // currently best scoreing target
+ float m_score; // currently best scoreing target's score
+
+ m_score = 0;
+ if(self.enemy && self.enemy.takedamage && turret_validate_target(self,self.enemy,self.target_validate_flags) > 0)
+ {
+ e_enemy = self.enemy;
+ m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias;
+ }
+ else
+ e_enemy = self.enemy = world;
+
+ e = findradius(self.origin, self.target_range);
+
+ // Nothing to aim at?
+ if (!e)
+ return world;
+
+ while (e)
+ {
+ if(e.takedamage)
+ {
+ float f = turret_validate_target(self, e, self.target_select_flags);
+ //dprint("F is: ", ftos(f), "\n");
+ if ( f > 0)
+ {
+ score = self.turret_score_target(self,e);
+ if ((score > m_score) && (score > 0))
+ {
+ e_enemy = e;
+ m_score = score;
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ return e_enemy;
+}
+
+
+/*
+ + = implemented
+ - = not implemented
+
+ + TFL_FIRECHECK_NO
+ + TFL_FIRECHECK_WORLD
+ + TFL_FIRECHECK_DEAD
+ + TFL_FIRECHECK_DISTANCES
+ - TFL_FIRECHECK_LOS
+ + TFL_FIRECHECK_AIMDIST
+ + TFL_FIRECHECK_REALDIST
+ - TFL_FIRECHECK_ANGLEDIST
+ - TFL_FIRECHECK_TEAMCECK
+ + TFL_FIRECHECK_AFF
+ + TFL_FIRECHECK_AMMO_OWN
+ + TFL_FIRECHECK_AMMO_OTHER
+ + TFL_FIRECHECK_REFIRE
+*/
+
+/**
+** Preforms pre-fire checks based on the uints firecheck_flags
+**/
+float turret_firecheck()
+{
+ // This one just dont care =)
+ if (self.firecheck_flags & TFL_FIRECHECK_NO)
+ return 1;
+
+ if (self.enemy == world)
+ return 0;
+
+ // Ready?
+ if (self.firecheck_flags & TFL_FIRECHECK_REFIRE)
+ if (self.attack_finished_single > time) return 0;
+
+ // Special case: volly fire turret that has to fire a full volly if a shot was fired.
+ if (self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
+ if (self.volly_counter != self.shot_volly)
+ if(self.ammo >= self.shot_dmg)
+ return 1;
+
+ // Lack of zombies makes shooting dead things unnecessary :P
+ if (self.firecheck_flags & TFL_FIRECHECK_DEAD)
+ if (self.enemy.deadflag != DEAD_NO)
+ return 0;
+
+ // Own ammo?
+ if (self.firecheck_flags & TFL_FIRECHECK_AMMO_OWN)
+ if (self.ammo < self.shot_dmg)
+ return 0;
+
+ // Other's ammo? (support-supply units)
+ if (self.firecheck_flags & TFL_FIRECHECK_AMMO_OTHER)
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return 0;
+
+ // Target of opertunity?
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ {
+ self.enemy = self.tur_impactent;
+ return 1;
+ }
+
+ if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
+ {
+ // To close?
+ if (self.tur_dist_aimpos < self.target_range_min)
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ return 1; // Target of opertunity?
+ else
+ return 0;
+ }
+
+ // Try to avoid FF?
+ if (self.firecheck_flags & TFL_FIRECHECK_AFF)
+ if (self.tur_impactent.team == self.team)
+ return 0;
+
+ // aim<->predicted impact
+ if (self.firecheck_flags & TFL_FIRECHECK_AIMDIST)
+ if (self.tur_dist_impact_to_aimpos > self.aim_firetolerance_dist)
+ return 0;
+
+ // Volly status
+ if (self.shot_volly > 1)
+ if (self.volly_counter == self.shot_volly)
+ if (self.ammo < (self.shot_dmg * self.shot_volly))
+ return 0;
+
+ /*if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
+ if(self.tur_impactent != self.enemy)
+ return 0;*/
+
+ return 1;
+}
+
+void turret_fire()
+{
+ if (autocvar_g_turrets_nofire != 0)
+ return;
+
+ TUR_ACTION(self.turretid, TR_ATTACK);
+
+ self.attack_finished_single = time + self.shot_refire;
+ self.ammo -= self.shot_dmg;
+ self.volly_counter = self.volly_counter - 1;
+
+ if (self.volly_counter <= 0)
+ {
+ self.volly_counter = self.shot_volly;
+
+ if (self.shoot_flags & TFL_SHOOT_CLEARTARGET)
+ self.enemy = world;
+
+ if (self.shot_volly > 1)
+ self.attack_finished_single = time + self.shot_volly_refire;
+ }
+
+#ifdef TURRET_DEBUG
+ if (self.enemy) paint_target3(self.tur_aimpos, 64, self.tur_debug_rvec, self.tur_impacttime + 0.25);
+#endif
+}
+
+void turret_think()
+{
+ entity e;
+
+ self.nextthink = time + self.ticrate;
+
+ // ONS uses somewhat backwards linking.
+ if (teamplay)
+ {
+ if (g_onslaught)
+ if (self.target)
+ {
+ e = find(world, targetname,self.target);
+ if (e != world)
+ self.team = e.team;
+ }
+
+ if (self.team != self.tur_head.team)
+ turret_respawn();
+ }
+
+#ifdef TURRET_DEBUG
+ if (self.tur_debug_tmr1 < time)
+ {
+ if (self.enemy) paint_target (self.enemy,128,self.tur_debug_rvec,0.9);
+ paint_target(self,256,self.tur_debug_rvec,0.9);
+ self.tur_debug_tmr1 = time + 1;
+ }
+#endif
+
+ // Handle ammo
- if not (self.active)
++ if (!(self.spawnflags & TSF_NO_AMMO_REGEN))
+ if (self.ammo < self.ammo_max)
+ self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max);
+
+ // Inactive turrets needs to run the think loop,
+ // So they can handle animation and wake up if need be.
- if not(self.aim_flags & TFL_AIM_NO)
++ if(!self.active)
+ {
+ turret_track();
+ return;
+ }
+
+ // This is typicaly used for zaping every target in range
+ // turret_fusionreactor uses this to recharge friendlys.
+ if (self.shoot_flags & TFL_SHOOT_HITALLVALID)
+ {
+ // Do a self.turret_fire for every valid target.
+ e = findradius(self.origin,self.target_range);
+ while (e)
+ {
+ if(e.takedamage)
+ {
+ if (turret_validate_target(self,e,self.target_validate_flags))
+ {
+ self.enemy = e;
+
+ turret_do_updates(self);
+
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+ }
+
+ e = e.chain;
+ }
+ self.enemy = world;
+ }
+ else if(self.shoot_flags & TFL_SHOOT_CUSTOM)
+ {
+ // This one is doing something.. oddball. assume its handles what needs to be handled.
+
+ // Predict?
- if not(self.track_flags & TFL_TRACK_NO)
++ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch?
- if not(self.aim_flags & TFL_AIM_NO)
++ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire?
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+ else
+ {
+ // Special case for volly always. if it fired once it must compleate the volly.
+ if(self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
+ if(self.volly_counter != self.shot_volly)
+ {
+ // Predict or whatnot
- if not(self.track_flags & TFL_TRACK_NO)
++ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch
- if not(self.track_flags & TFL_TRACK_NO)
++ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire!
+ if (self.turret_firecheckfunc() != 0)
+ turret_fire();
+
+ TUR_ACTION(self.turretid, TR_THINK);
+
+ return;
+ }
+
+ // Check if we have a vailid enemy, and try to find one if we dont.
+
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
+ // No target, just go to idle, do any custom stuff and bail.
+ if (self.enemy == world)
+ {
+ // Turn & pitch
- if not(self.aim_flags & TFL_AIM_NO)
++ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ TUR_ACTION(self.turretid, TR_THINK);
+
+ // And bail.
+ return;
+ }
+ else
+ self.lip = time + autocvar_g_turrets_aimidle_delay; // Keep track of the last time we had a target.
+
+ // Predict?
- if not(self.track_flags & TFL_TRACK_NO)
++ if(!(self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_aim_generic();
+
+ // Turn & pitch?
- if not(autocvar_g_turrets)
++ if(!(self.track_flags & TFL_TRACK_NO))
+ turret_track();
+
+ turret_do_updates(self);
+
+ // Fire?
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+
+ TUR_ACTION(self.turretid, TR_THINK);
+}
+
+/*
+ When .used a turret switch team to activator.team.
+ If activator is world, the turret go inactive.
+*/
+void turret_use()
+{
+ dprint("Turret ",self.netname, " used by ", activator.classname, "\n");
+
+ self.team = activator.team;
+
+ if(self.team == 0)
+ self.active = ACTIVE_NOT;
+ else
+ self.active = ACTIVE_ACTIVE;
+
+}
+
+void turret_link()
+{
+ Net_LinkEntity(self, TRUE, 0, turret_send);
+ self.think = turret_think;
+ self.nextthink = time;
+ self.tur_head.effects = EF_NODRAW;
+}
+
+void turrets_manager_think()
+{
+ self.nextthink = time + 1;
+
+ entity e;
+ if (autocvar_g_turrets_reloadcvars == 1)
+ {
+ e = nextent(world);
+ while (e)
+ {
+ if (e.turret_flags & TUR_FLAG_ISTURRET)
+ {
+ load_unit_settings(e,e.cvar_basename,1);
+ TUR_ACTION(self.turretid, TR_THINK);
+ }
+
+ e = nextent(e);
+ }
+ cvar_set("g_turrets_reloadcvars","0");
+ }
+}
+
+float turret_initialize(float tur_id)
+{
- if not (e)
++ if(!autocvar_g_turrets)
+ return FALSE;
+
+ entity e;
+ entity tur = get_turretinfo(tur_id);
+ if(tur.turretid == 0)
+ return FALSE; // invalid turret
+
+ e = find(world, classname, "turret_manager");
- if not(self.spawnflags & TSF_SUSPENDED)
++ if(!e)
+ {
+ e = spawn();
+ e.classname = "turret_manager";
+ e.think = turrets_manager_think;
+ e.nextthink = time + 2;
+ }
+
- if not(self.team || teamplay) { self.team = MAX_SHOT_DISTANCE; }
- if not(self.ticrate) { self.ticrate = ((self.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); }
- if not(self.health) { self.health = 1000; }
- if not(self.shot_refire) { self.shot_refire = 1; }
- if not(self.tur_shotorg) { self.tur_shotorg = '50 0 50'; }
- if not(self.turret_flags) { self.turret_flags = TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER; }
- if not(self.damage_flags) { self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE; }
- if not(self.aim_flags) { self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; }
- if not(self.track_type) { self.track_type = TFL_TRACKTYPE_STEPMOTOR; }
- if not(self.track_flags) { self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROTATE; }
- if not(self.ammo_flags) { self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE; }
- if not(self.target_select_flags){ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_ANGLELIMITS; }
- if not(self.firecheck_flags) { self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_LOS
++ if(!(self.spawnflags & TSF_SUSPENDED))
+ builtin_droptofloor();
+
+ self.cvar_basename = tur.cvar_basename;
+ load_unit_settings(self, self.cvar_basename, 0);
+
- if not(self.track_accel_pitch) { self.track_accel_pitch = 0.5; }
- if not(self.track_accel_rotate) { self.track_accel_rotate = 0.5; }
- if not(self.track_blendrate) { self.track_blendrate = 0.35; }
++ if(!self.team || !teamplay) { self.team = MAX_SHOT_DISTANCE; }
++ if(!self.ticrate) { self.ticrate = ((self.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); }
++ if(!self.health) { self.health = 1000; }
++ if(!self.shot_refire) { self.shot_refire = 1; }
++ if(!self.tur_shotorg) { self.tur_shotorg = '50 0 50'; }
++ if(!self.turret_flags) { self.turret_flags = TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER; }
++ if(!self.damage_flags) { self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE; }
++ if(!self.aim_flags) { self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE; }
++ if(!self.track_type) { self.track_type = TFL_TRACKTYPE_STEPMOTOR; }
++ if(!self.track_flags) { self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROTATE; }
++ if(!self.ammo_flags) { self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE; }
++ if(!self.target_select_flags) { self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_ANGLELIMITS; }
++ if(!self.firecheck_flags) { self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_LOS
+ | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_REFIRE; }
+
+ if(self.track_type != TFL_TRACKTYPE_STEPMOTOR)
+ {
+ // Fluid / Ineria mode. Looks mutch nicer.
+ // Can reduce aim preformance alot, needs a bit diffrent aimspeed
+
+ self.aim_speed = bound(0.1, ((!self.aim_speed) ? 180 : self.aim_speed), 1000);
+
- if not(self.tur_defend)
++ if(!self.track_accel_pitch) { self.track_accel_pitch = 0.5; }
++ if(!self.track_accel_rotate) { self.track_accel_rotate = 0.5; }
++ if(!self.track_blendrate) { self.track_blendrate = 0.35; }
+ }
+
+ self.respawntime = max(-1, ((!self.respawntime) ? 60 : self.respawntime));
+ self.shot_refire = bound(0.01, ((!self.shot_refire) ? 1 : self.shot_refire), 9999);
+ self.shot_dmg = max(1, ((!self.shot_dmg) ? self.shot_refire * 50 : self.shot_dmg));
+ self.shot_radius = max(1, ((!self.shot_radius) ? self.shot_dmg * 0.5 : self.shot_radius));
+ self.shot_speed = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
+ self.shot_spread = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
+ self.shot_force = bound(0.001, ((!self.shot_force) ? self.shot_dmg * 0.5 + self.shot_radius * 0.5 : self.shot_force), 5000);
+ self.shot_volly = bound(1, ((!self.shot_volly) ? 1 : self.shot_volly), floor(self.ammo_max / self.shot_dmg));
+ self.shot_volly_refire = bound(self.shot_refire, ((!self.shot_volly_refire) ? self.shot_refire * self.shot_volly : self.shot_volly_refire), 60);
+ self.target_range = bound(0, ((!self.target_range) ? self.shot_speed * 0.5 : self.target_range), MAX_SHOT_DISTANCE);
+ self.target_range_min = bound(0, ((!self.target_range_min) ? self.shot_radius * 2 : self.target_range_min), MAX_SHOT_DISTANCE);
+ self.target_range_optimal = bound(0, ((!self.target_range_optimal) ? self.target_range * 0.5 : self.target_range_optimal), MAX_SHOT_DISTANCE);
+ self.aim_maxrotate = bound(0, ((!self.aim_maxrotate) ? 90 : self.aim_maxrotate), 360);
+ self.aim_maxpitch = bound(0, ((!self.aim_maxpitch) ? 20 : self.aim_maxpitch), 90);
+ self.aim_speed = bound(0.1, ((!self.aim_speed) ? 36 : self.aim_speed), 1000);
+ self.aim_firetolerance_dist = bound(0.1, ((!self.aim_firetolerance_dist) ? 5 + (self.shot_radius * 2) : self.aim_firetolerance_dist), MAX_SHOT_DISTANCE);
+ self.target_select_rangebias = bound(-10, ((!self.target_select_rangebias) ? 1 : self.target_select_rangebias), 10);
+ self.target_select_samebias = bound(-10, ((!self.target_select_samebias) ? 1 : self.target_select_samebias), 10);
+ self.target_select_anglebias = bound(-10, ((!self.target_select_anglebias) ? 1 : self.target_select_anglebias), 10);
+ self.target_select_missilebias = bound(-10, ((!self.target_select_missilebias) ? 1 : self.target_select_missilebias), 10);
+ self.target_select_playerbias = bound(-10, ((!self.target_select_playerbias) ? 1 : self.target_select_playerbias), 10);
+ self.ammo_max = max(self.shot_dmg, ((!self.ammo_max) ? self.shot_dmg * 10 : self.ammo_max));
+ self.ammo_recharge = max(0, ((!self.ammo_recharge) ? self.shot_dmg * 0.5 : self.ammo_recharge));
+
+ self.turret_flags = TUR_FLAG_ISTURRET | (tur.spawnflags);
+
+ if(self.turret_flags & TUR_FLAG_SPLASH)
+ self.aim_flags |= TFL_AIM_SPLASH;
+
+ if(self.turret_flags & TUR_FLAG_MISSILE)
+ self.target_select_flags |= TFL_TARGETSELECT_MISSILES;
+
+ if(self.turret_flags & TUR_FLAG_PLAYER)
+ self.target_select_flags |= TFL_TARGETSELECT_PLAYERS;
+
+ if(self.spawnflags & TSL_NO_RESPAWN)
+ self.damage_flags |= TFL_DMG_DEATH_NORESPAWN;
+
+ if (self.turret_flags & TUR_FLAG_SUPPORT)
+ self.turret_score_target = turret_targetscore_support;
+ else
+ self.turret_score_target = turret_targetscore_generic;
+
+ ++turret_count;
+
+ setmodel(self, tur.model);
+ setsize(self, tur.mins, tur.maxs);
+
+ self.turretid = tur_id;
+ self.classname = "turret_main";
+ self.active = ACTIVE_ACTIVE;
+ self.effects = EF_NODRAW;
+ self.netname = TUR_NAME(tur_id);
+ self.ticrate = bound(sys_frametime, self.ticrate, 60);
+ self.max_health = self.health;
+ self.target_validate_flags = self.target_select_flags;
+ self.ammo = self.ammo_max;
+ self.ammo_recharge *= self.ticrate;
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.view_ofs = '0 0 0';
+ self.turret_firecheckfunc = turret_firecheck;
+ self.event_damage = turret_damage;
+ self.use = turret_use;
+ self.bot_attack = TRUE;
+ self.nextthink = time + 1;
+ self.nextthink += turret_count * sys_frametime;
+
+ self.tur_head = spawn();
+ setmodel(self.tur_head, tur.head_model);
+ setsize(self.tur_head, '0 0 0', '0 0 0');
+ setorigin(self.tur_head, '0 0 0');
+ setattachment(self.tur_head, self, "tag_head");
+
+ self.tur_head.netname = self.tur_head.classname = "turret_head";
+ self.tur_head.team = self.team;
+ self.tur_head.owner = self;
+ self.tur_head.takedamage = DAMAGE_NO;
+ self.tur_head.solid = SOLID_NOT;
+ self.tur_head.movetype = self.movetype;
+
- }
++ if(!self.tur_defend)
+ if(self.target != "")
+ {
+ self.tur_defend = find(world, targetname, self.target);
+ if (self.tur_defend == world)
+ {
+ self.target = "";
+ dprint("Turret has invalid defendpoint!\n");
+ }
+ }
+
+ if (self.tur_defend)
+ self.idle_aim = self.tur_head.angles + angleofs(self.tur_head, self.tur_defend);
+ else
+ self.idle_aim = '0 0 0';
+
+#ifdef TURRET_DEBUG
+ self.tur_debug_start = self.nextthink;
+ while (vlen(self.tur_debug_rvec) < 2)
+ self.tur_debug_rvec = randomvec() * 4;
+
+ self.tur_debug_rvec_x = fabs(self.tur_debug_rvec_x);
+ self.tur_debug_rvec_y = fabs(self.tur_debug_rvec_y);
+ self.tur_debug_rvec_z = fabs(self.tur_debug_rvec_z);
+#endif
+
+ turret_link();
+ turret_respawn();
+ turret_tag_fire_update();
+
+ TUR_ACTION(tur_id, TR_SETUP);
+
+ if(MUTATOR_CALLHOOK(TurretSpawn))
+ return FALSE;
+
+ return TRUE;
++}
--- /dev/null
- if not(autocvar_g_turrets) { remove(self); return; }
+void spawnfunc_turret_targettrigger();
+void turret_targettrigger_touch();
+
+void turret_targettrigger_touch()
+{
+ entity e;
+ if (self.cnt > time) return;
+ entity oldself;
+ oldself = self;
+
+ e = find(world, targetname, self.target);
+ while (e)
+ {
+ if (e.turret_flags & TUR_FLAG_RECIEVETARGETS)
+ {
+ self = e;
+ if(e.turret_addtarget)
+ e.turret_addtarget(other,oldself);
+ }
+
+ e = find(e, targetname, oldself.target);
+ }
+
+ oldself.cnt = time + 0.5;
+
+ self = oldself;
+}
+
+/*QUAKED turret_targettrigger (.5 .5 .5) ?
+*/
+void spawnfunc_turret_targettrigger()
+{
++ if(!autocvar_g_turrets) { remove(self); return; }
+
+ InitTrigger ();
+
+ self.touch = turret_targettrigger_touch;
+}
--- /dev/null
-
- #define EWHEEL_SETTINGS(turret) \
- TUR_ADD_CVAR(turret, speed_fast) \
- TUR_ADD_CVAR(turret, speed_slow) \
- TUR_ADD_CVAR(turret, speed_slower) \
- TUR_ADD_CVAR(turret, speed_stop) \
- TUR_ADD_CVAR(turret, turnrate)
-
-
- #ifdef SVQC
- EWHEEL_SETTINGS(ewheel)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ EWHEEL,
+/* function */ t_ewheel,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
+/* mins,maxs */ '-32 -32 0', '32 32 48',
+/* model */ "ewheel-base2.md3",
+/* head_model */ "ewheel-gun1.md3",
+/* netname */ "ewheel",
+/* fullname */ _("eWheel Turret")
+);
- movelib_move_simple(v_forward, TUR_CVAR(ewheel, speed_fast), 0.4);
+#else
+#ifdef SVQC
++float autocvar_g_turrets_unit_ewheel_speed_fast;
++float autocvar_g_turrets_unit_ewheel_speed_slow;
++float autocvar_g_turrets_unit_ewheel_speed_slower;
++float autocvar_g_turrets_unit_ewheel_speed_stop;
++float autocvar_g_turrets_unit_ewheel_turnrate;
++
+const float ewheel_anim_stop = 0;
+const float ewheel_anim_fwd_slow = 1;
+const float ewheel_anim_fwd_fast = 2;
+const float ewheel_anim_bck_slow = 3;
+const float ewheel_anim_bck_fast = 4;
+
+//#define EWHEEL_FANCYPATH
+void ewheel_move_path()
+{
+#ifdef EWHEEL_FANCYPATH
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+#endif
+
+ if (self.pathcurrent)
+ {
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
- movelib_move_simple(v_forward, TUR_CVAR(ewheel, speed_fast), 0.4);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+}
+
+void ewheel_move_enemy()
+{
+ float newframe;
+
+ self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+
+ self.moveto = self.origin + self.steerto * 128;
+
+ if (self.tur_dist_enemy > self.target_range_optimal)
+ {
+ if ( self.tur_head.spawnshieldtime < 1 )
+ {
+ newframe = ewheel_anim_fwd_fast;
- movelib_move_simple(v_forward, TUR_CVAR(ewheel, speed_slow), 0.4);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+ }
+ else if (self.tur_head.spawnshieldtime < 2)
+ {
+
+ newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward, TUR_CVAR(ewheel, speed_slower), 0.4);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_fwd_slow;
- movelib_move_simple(v_forward * -1, TUR_CVAR(ewheel, speed_slow), 0.4);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
+ }
+ }
+ else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
+ {
+ newframe = ewheel_anim_bck_slow;
- movelib_beak_simple(TUR_CVAR(ewheel, speed_stop));
++ movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+ }
+ else
+ {
+ newframe = ewheel_anim_stop;
- movelib_beak_simple(TUR_CVAR(ewheel, speed_stop));
++ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+ }
+
+ turrets_setframe(newframe, FALSE);
+}
+
+void ewheel_move_idle()
+{
+ if(self.frame != 0)
+ {
+ self.SendFlags |= TNSF_ANIM;
+ self.anim_start_time = time;
+ }
+
+ self.frame = 0;
+ if (vlen(self.velocity))
- void spawnfunc_turret_ewheel() { if not(turret_initialize(TUR_EWHEEL)) remove(self); }
++ movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+}
+
- self.tur_head.aim_speed = TUR_CVAR(ewheel, turnrate);
++void spawnfunc_turret_ewheel() { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
+
+float t_ewheel(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ float i;
+ entity _mis;
+
+ for (i = 0; i < 1; ++i)
+ {
+ turret_do_updates(self);
+
+ _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE);
+ _mis.missile_flags = MIF_SPLASH;
+
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ self.tur_head.frame += 2;
+
+ if (self.tur_head.frame > 3)
+ self.tur_head.frame = 0;
+ }
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ float vz;
+ vector wish_angle, real_angle;
+
+ vz = self.velocity_z;
+
+ self.angles_x = anglemods(self.angles_x);
+ self.angles_y = anglemods(self.angles_y);
+
+ fixedmakevectors(self.angles);
+
+ wish_angle = normalize(self.steerto);
+ wish_angle = vectoangles(wish_angle);
+ real_angle = wish_angle - self.angles;
+ real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
+
+ self.tur_head.spawnshieldtime = fabs(real_angle_y);
+ real_angle_y = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
+ self.angles_y = (self.angles_y + real_angle_y);
+
+ if(self.enemy)
+ ewheel_move_enemy();
+ else if(self.pathcurrent)
+ ewheel_move_path();
+ else
+ ewheel_move_idle();
+
+ self.velocity_z = vz;
+
+ if(vlen(self.velocity))
+ self.SendFlags |= TNSF_MOVE;
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ self.velocity = '0 0 0';
+
+#ifdef EWHEEL_FANCYPATH
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ entity e;
+
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ self.velocity = '0 0 0';
+ self.enemy = world;
+
+ setorigin(self, self.pos1);
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ dprint("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ {
+
+#ifdef EWHEEL_FANCYPATH
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+ }
+
+ self.iscreature = TRUE;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = TRUE;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.idle_aim = '0 0 0';
+ self.pos1 = self.origin;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.frame = self.tur_head.frame = 1;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+
+ // Convert from dgr / sec to dgr / tic
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(EWHEEL_SETTINGS(ewheel))
- return TRUE;
- }
++ self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
+ self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/ewheel-base2.md3");
+ precache_model ("models/turrets/ewheel-gun1.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+void ewheel_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.05)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_ewheel(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = ewheel_draw;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/ewheel-base2.md3");
+ precache_model ("models/turrets/ewheel-gun1.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define FLAC_SETTINGS(turret)
-
-
- #ifdef SVQC
- FLAC_SETTINGS(flac)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ FLAC,
+/* function */ t_flac,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "flac.md3",
+/* netname */ "flac",
+/* fullname */ _("FLAC Cannon")
+);
-
+#else
+#ifdef SVQC
- void spawnfunc_turret_flac() { if not(turret_initialize(TUR_FLAC)) remove(self); }
+void turret_flac_projectile_think_explode()
+{
+ if(self.enemy != world)
+ if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
+ setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+
+#ifdef TURRET_DEBUG
+ float d;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+#endif
+ remove(self);
+}
+
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(FLAC_SETTINGS(flac))
- return TRUE;
- }
++void spawnfunc_turret_flac() { if(!turret_initialize(TUR_FLAC)) remove(self); }
+
+float t_flac(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity proj;
+
+ turret_tag_fire_update();
+
+ proj = turret_projectile("weapons/hagar_fire.wav", 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ proj.think = turret_flac_projectile_think_explode;
+ proj.nextthink = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
+ proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+
+ self.tur_head.frame = self.tur_head.frame + 1;
+ if (self.tur_head.frame >= 4)
+ self.tur_head.frame = 0;
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/flac.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_flac(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/flac.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define FUSIONREACTOR_SETTINGS(turret)
-
-
- #ifdef SVQC
- FUSIONREACTOR_SETTINGS(fusionreactor)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ FUSIONREACTOR,
+/* function */ t_fusionreactor,
+/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
+/* mins,maxs */ '-34 -34 0', '34 34 90',
+/* model */ "base.md3",
+/* head_model */ "reactor.md3",
+/* netname */ "fusionreactor",
+/* fullname */ _("Fusion Reactor")
+);
-
+#else
+#ifdef SVQC
- if not (self.enemy.ammo_flags & TFL_AMMO_ENERGY)
+float turret_fusionreactor_firecheck()
+{
+ if (self.attack_finished_single > time)
+ return 0;
+
+ if (self.enemy.deadflag != DEAD_NO)
+ return 0;
+
+ if (self.enemy == world)
+ return 0;
+
+ if (self.ammo < self.shot_dmg)
+ return 0;
+
+ if (self.enemy.ammo >= self.enemy.ammo_max)
+ return 0;
+
+ if (vlen(self.enemy.origin - self.origin) > self.target_range)
+ return 0;
+
+ if(self.team != self.enemy.team)
+ return 0;
+
- void spawnfunc_turret_fusionreactor() { if not(turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
++ if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
+ return 0;
+
+ return 1;
+}
+
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(FUSIONREACTOR_SETTINGS(fusionreactor))
- return TRUE;
- }
++void spawnfunc_turret_fusionreactor() { if(!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
+
+float t_fusionreactor(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ vector fl_org;
+
+ self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
+ te_smallflash(fl_org);
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+ self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
+ self.firecheck_flags = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
+ self.shoot_flags = TFL_SHOOT_HITALLVALID;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ self.tur_head.scale = 0.75;
+ self.tur_head.avelocity = '0 50 0';
+
+ self.turret_firecheckfunc = turret_fusionreactor_firecheck;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/reactor.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_fusionreactor(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/reactor.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define HELLION_SETTINGS(turret) \
- TUR_ADD_CVAR(turret, shot_speed_gain) \
- TUR_ADD_CVAR(turret, shot_speed_max)
-
-
- #ifdef SVQC
- HELLION_SETTINGS(hellion)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ HELLION,
+/* function */ t_hellion,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hellion.md3",
+/* netname */ "hellion",
+/* fullname */ _("Hellion Missile Turret")
+);
- self.velocity = olddir * min(vlen(self.velocity) * TUR_CVAR(hellion, shot_speed_gain), TUR_CVAR(hellion, shot_speed_max));
+#else
+#ifdef SVQC
++float autocvar_g_turrets_unit_hellion_shot_speed_gain;
++float autocvar_g_turrets_unit_hellion_shot_speed_max;
+
+void turret_hellion_missile_think()
+{
+ vector olddir,newdir;
+ vector pre_pos;
+ float itime;
+
+ self.nextthink = time + 0.05;
+
+ olddir = normalize(self.velocity);
+
+ if(self.max_health < time)
+ turret_projectile_explode();
+
+ // Enemy dead? just keep on the current heading then.
+ if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
+ {
+
+ // Make sure we dont return to tracking a respawned player
+ self.enemy = world;
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
+ turret_projectile_explode();
+
+ // Accelerate
- self.velocity = newdir * min(vlen(self.velocity) * TUR_CVAR(hellion, shot_speed_gain), TUR_CVAR(hellion, shot_speed_max));
++ self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ UpdateCSQCProjectile(self);
+
+ return;
+ }
+
+ // Enemy in range?
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+ turret_projectile_explode();
+
+ // Predict enemy position
+ itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
+ pre_pos = self.enemy.origin + self.enemy.velocity * itime;
+
+ pre_pos = (pre_pos + self.enemy.origin) * 0.5;
+
+ // Find out the direction to that place
+ newdir = normalize(pre_pos - self.origin);
+
+ // Turn
+ newdir = normalize(olddir + newdir * 0.35);
+
+ // Turn model
+ self.angles = vectoangles(self.velocity);
+
+ // Accelerate
- void spawnfunc_turret_hellion() { if not(turret_initialize(TUR_HELLION)) remove(self); }
++ self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+ if (itime < 0.05)
+ self.think = turret_projectile_explode;
+
+ UpdateCSQCProjectile(self);
+}
+
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(HELLION_SETTINGS(hellion))
- return TRUE;
- }
++void spawnfunc_turret_hellion() { if(!turret_initialize(TUR_HELLION)) remove(self); }
+
+float t_hellion(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ if(self.tur_head.frame != 0)
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
+ else
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
+
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;
+ missile.flags = FL_PROJECTILE;
+ missile.max_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+ self.tur_head.frame += 1;
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame += 1;
+
+ if (self.tur_head.frame >= 7)
+ self.tur_head.frame = 0;
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hellion.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hellion(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hellion.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define HK_SETTINGS(turret) \
- TUR_ADD_CVAR(turret, shot_speed) \
- TUR_ADD_CVAR(turret, shot_speed_accel) \
- TUR_ADD_CVAR(turret, shot_speed_accel2) \
- TUR_ADD_CVAR(turret, shot_speed_decel) \
- TUR_ADD_CVAR(turret, shot_speed_max) \
- TUR_ADD_CVAR(turret, shot_speed_turnrate)
-
-
- #ifdef SVQC
- HK_SETTINGS(hk)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ HK,
+/* function */ t_hk,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "hk.md3",
+/* netname */ "hk",
+/* fullname */ _("Hunter-Killer Turret")
+);
- if ( ((ff < 0.7) || (ad > 4)) && (myspeed > TUR_CVAR(hk, shot_speed)) )
- myspeed = max(myspeed * TUR_CVAR(hk, shot_speed_decel), TUR_CVAR(hk, shot_speed));
+#else
+#ifdef SVQC
++float autocvar_g_turrets_unit_hk_shot_speed;
++float autocvar_g_turrets_unit_hk_shot_speed_accel;
++float autocvar_g_turrets_unit_hk_shot_speed_accel2;
++float autocvar_g_turrets_unit_hk_shot_speed_decel;
++float autocvar_g_turrets_unit_hk_shot_speed_max;
++float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
+
+//#define TURRET_DEBUG_HK
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+float hk_is_valid_target(entity e_target)
+{
+ if (e_target == world)
+ return 0;
+
+ // If only this was used more..
+ if (e_target.flags & FL_NOTARGET)
+ return 0;
+
+ // Cant touch this
+ if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
+ return 0;
+
+ // player
+ if (IS_CLIENT(e_target))
+ {
+ if (self.owner.target_select_playerbias < 0)
+ return 0;
+
+ if (e_target.deadflag != DEAD_NO)
+ return 0;
+ }
+
+ // Missile
+ if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
+ return 0;
+
+ // Team check
+ if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
+ return 0;
+
+ return 1;
+}
+
+void turret_hk_missile_think()
+{
+ vector vu, vd, vf, vl, vr, ve; // Vector (direction)
+ float fu, fd, ff, fl, fr, fe; // Fraction to solid
+ vector olddir,wishdir,newdir; // Final direction
+ float lt_for; // Length of Trace FORwrad
+ float lt_seek; // Length of Trace SEEK (left, right, up down)
+ float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+ vector pre_pos;
+ float myspeed;
+ entity e;
+ float ad,edist;
+
+ self.nextthink = time + self.ticrate;
+
+ //if (self.cnt < time)
+ // turret_hk_missile_explode();
+
+ if (self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ // Pick the closest valid target.
+ if (!self.enemy)
+ {
+ e = findradius(self.origin, 5000);
+ while (e)
+ {
+ if (hk_is_valid_target(e))
+ {
+ if (!self.enemy)
+ self.enemy = e;
+ else
+ if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
+ self.enemy = e;
+ }
+ e = e.chain;
+ }
+ }
+
+ self.angles = vectoangles(self.velocity);
+ self.angles_x = self.angles_x * -1;
+ makevectors(self.angles);
+ self.angles_x = self.angles_x * -1;
+
+ if (self.enemy)
+ {
+ edist = vlen(self.origin - self.enemy.origin);
+ // Close enougth to do decent damage?
+ if ( edist <= (self.owner.shot_radius * 0.25) )
+ {
+ turret_projectile_explode();
+ return;
+ }
+
+ // Get data on enemy position
+ pre_pos = self.enemy.origin +
+ self.enemy.velocity *
+ min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
+
+ traceline(self.origin, pre_pos,TRUE,self.enemy);
+ ve = normalize(pre_pos - self.origin);
+ fe = trace_fraction;
+
+ }
+ else
+ {
+ edist = 0;
+ ve = '0 0 0';
+ fe = 0;
+ }
+
+ if ((fe != 1) || (self.enemy == world) || (edist > 1000))
+ {
+ myspeed = vlen(self.velocity);
+
+ lt_for = myspeed * 3;
+ lt_seek = myspeed * 2.95;
+
+ // Trace forward
+ traceline(self.origin, self.origin + v_forward * lt_for,FALSE,self);
+ vf = trace_endpos;
+ ff = trace_fraction;
+
+ // Find angular offset
+ ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
+
+ // To close to something, Slow down!
- if ( (ff > 0.7) && (myspeed < TUR_CVAR(hk, shot_speed_max)) )
- myspeed = min(myspeed * TUR_CVAR(hk, shot_speed_accel), TUR_CVAR(hk, shot_speed_max));
++ if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
++ myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
+
+ // Failry clear, accelerate.
- if (myspeed < TUR_CVAR(hk, shot_speed_max))
- myspeed = min(myspeed * TUR_CVAR(hk, shot_speed_accel2),TUR_CVAR(hk, shot_speed_max));
++ if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
++ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Setup trace pitch
+ pt_seek = 1 - ff;
+ pt_seek = bound(0.15,pt_seek,0.8);
+ if (ff < 0.5) pt_seek = 1;
+
+ // Trace left
+ traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,FALSE,self);
+ vl = trace_endpos;
+ fl = trace_fraction;
+
+ // Trace right
+ traceline(self.origin, self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,FALSE,self);
+ vr = trace_endpos;
+ fr = trace_fraction;
+
+ // Trace up
+ traceline(self.origin, self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,FALSE,self);
+ vu = trace_endpos;
+ fu = trace_fraction;
+
+ // Trace down
+ traceline(self.origin, self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,FALSE,self);
+ vd = trace_endpos;
+ fd = trace_fraction;
+
+ vl = normalize(vl - self.origin);
+ vr = normalize(vr - self.origin);
+ vu = normalize(vu - self.origin);
+ vd = normalize(vd - self.origin);
+
+ // Panic tresh passed, find a single direction and turn as hard as we can
+ if (pt_seek == 1)
+ {
+ wishdir = v_right;
+ if (fl > fr) wishdir = -1 * v_right;
+ if (fu > fl) wishdir = v_up;
+ if (fd > fu) wishdir = -1 * v_up;
+ }
+ else
+ {
+ // Normalize our trace vectors to make a smooth path
+ wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
+ }
+
+ if (self.enemy)
+ {
+ if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+ wishdir = (wishdir * (1 - fe)) + (ve * fe);
+ }
+ }
+ else
+ {
+ // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+ myspeed = vlen(self.velocity);
- if ((myspeed > TUR_CVAR(hk, shot_speed)) && (self.cnt > time))
- myspeed = min(myspeed * TUR_CVAR(hk, shot_speed_accel2),TUR_CVAR(hk, shot_speed_max));
++ if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
++ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ wishdir = ve;
+ }
+
- newdir = normalize(olddir + wishdir * TUR_CVAR(hk, shot_speed_turnrate));
++ if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
++ myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+ // Ranoutagazfish?
+ if (self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCE;
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(self.velocity);
- void spawnfunc_turret_hk() { if not(turret_initialize(TUR_HK)) remove(self); }
++ newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
+
+ // Set heading & speed
+ self.velocity = newdir * myspeed;
+
+ // Align model with new heading
+ self.angles = vectoangles(self.velocity);
+
+
+#ifdef TURRET_DEBUG_HK
+ //if(self.atime < time) {
+ if ((fe <= 0.99)||(edist > 1000))
+ {
+ te_lightning2(world,self.origin, self.origin + vr * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vl * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vu * lt_seek);
+ te_lightning2(world,self.origin, self.origin + vd * lt_seek);
+ te_lightning2(world,self.origin, vf);
+ }
+ else
+ {
+ te_lightning2(world,self.origin, self.enemy.origin);
+ }
+ bprint("Speed: ", ftos(rint(myspeed)), "\n");
+ bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
+ bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
+ self.atime = time + 0.2;
+ //}
+#endif
+
+ UpdateCSQCProjectile(self);
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{
+ if (e_target)
+ {
+ if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+ {
+ self.enemy = e_target;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(HK_SETTINGS(hk))
- return TRUE;
- }
++void spawnfunc_turret_hk() { if(!turret_initialize(TUR_HK)) remove(self); }
+
+float t_hk(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+ te_explosion (missile.origin);
+
+ missile.think = turret_hk_missile_think;
+ missile.nextthink = time + 0.25;
+ missile.movetype = MOVETYPE_BOUNCEMISSILE;
+ missile.velocity = self.tur_shotdir_updated * (self.shot_speed * 0.75);
+ missile.angles = vectoangles(missile.velocity);
+ missile.cnt = time + 30;
+ missile.ticrate = max(autocvar_sys_ticrate, 0.05);
+ missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+ self.shoot_flags = TFL_SHOOT_CLEARTARGET;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_addtarget = turret_hk_addtarget;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hk.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_hk(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hk.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define MACHINEGUN_SETTINGS(turret)
-
-
- #ifdef SVQC
- MACHINEGUN_SETTINGS(machinegun)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ MACHINEGUN,
+/* function */ t_machinegun,
+/* spawnflags */ TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "machinegun.md3",
+/* netname */ "machinegun",
+/* fullname */ _("Machinegun Turret")
+);
-
- void spawnfunc_turret_machinegun() { if not(turret_initialize(TUR_MACHINEGUN)) remove(self); }
+#else
+#ifdef SVQC
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
- endFireBallisticBullet();
++void spawnfunc_turret_machinegun() { if(!turret_initialize(TUR_MACHINEGUN)) remove(self); }
+
+float t_machinegun(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
-
- if not(autocvar_g_antilag_bullets)
- self.turret_flags |= TUR_FLAG_HITSCAN;
++ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
+
+ UziFlash();
+ setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(MACHINEGUN_SETTINGS(machinegun))
- return TRUE;
- }
++ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/machinegun.md3");
+ precache_sound ("weapons/uzi_fire.wav");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_machinegun(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/machinegun.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define MLRS_SETTINGS(turret)
-
-
- #ifdef SVQC
- MLRS_SETTINGS(mlrs)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ MLRS,
+/* function */ t_mlrs,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "mlrs.md3",
+/* netname */ "mlrs",
+/* fullname */ _("MLRS Turret")
+);
-
- void spawnfunc_turret_mlrs() { if not(turret_initialize(TUR_MLRS)) remove(self); }
+#else
+#ifdef SVQC
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(MLRS_SETTINGS(mlrs))
- return TRUE;
- }
++void spawnfunc_turret_mlrs() { if(!turret_initialize(TUR_MLRS)) remove(self); }
+
+float t_mlrs(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity missile;
+
+ turret_tag_fire_update();
+ missile = turret_projectile("weapons/rocket_fire.wav", 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
+ missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
+ missile.missile_flags = MIF_SPLASH;
+ te_explosion (missile.origin);
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ // 0 = full, 6 = empty
+ self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
+ if(self.tur_head.frame < 0)
+ {
+ dprint("ammo:",ftos(self.ammo),"\n");
+ dprint("shot_dmg:",ftos(self.shot_dmg),"\n");
+ }
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
+ self.volly_counter = self.shot_volly;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/mlrs.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_mlrs(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/mlrs.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define PHASER_SETTINGS(turret)
-
-
- #ifdef SVQC
- PHASER_SETTINGS(phaser)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PHASER,
+/* function */ t_phaser,
+/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "phaser.md3",
+/* netname */ "phaser",
+/* fullname */ _("Phaser Cannon")
+);
-
+#else
+#ifdef SVQC
- void spawnfunc_turret_phaser() { if not(turret_initialize(TUR_PHASER)) remove(self); }
+.float fireflag;
+
+float turret_phaser_firecheck()
+{
+ if (self.fireflag != 0) return 0;
+ return turret_firecheck();
+}
+
+void beam_think()
+{
+ if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
+ {
+ self.owner.attack_finished_single = time + self.owner.shot_refire;
+ self.owner.fireflag = 2;
+ self.owner.tur_head.frame = 10;
+ sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+ remove(self);
+ return;
+ }
+
+ turret_do_updates(self.owner);
+
+ if (time - self.shot_spread > 0)
+ {
+ self.shot_spread = time + 2;
+ sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
+ }
+
+
+ self.nextthink = time + self.ticrate;
+
+ self.owner.attack_finished_single = time + frametime;
+ entity oldself;
+ oldself = self;
+ self = self.owner;
+ FireImoBeam ( self.tur_shotorg,
+ self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
+ '-1 -1 -1' * self.shot_radius,
+ '1 1 1' * self.shot_radius,
+ self.shot_force,
+ oldself.shot_dmg,
+ 0.75,
+ DEATH_TURRET_PHASER);
+ self = oldself;
+ self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(PHASER_SETTINGS(phaser))
- return TRUE;
- }
++void spawnfunc_turret_phaser() { if(!turret_initialize(TUR_PHASER)) remove(self); }
+
+float t_phaser(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity beam;
+
+ beam = spawn();
+ beam.ticrate = 0.1; //autocvar_sys_ticrate;
+ setmodel(beam,"models/turrets/phaser_beam.md3");
+ beam.effects = EF_LOWPRECISION;
+ beam.solid = SOLID_NOT;
+ beam.think = beam_think;
+ beam.cnt = time + self.shot_speed;
+ beam.shot_spread = time + 2;
+ beam.nextthink = time;
+ beam.owner = self;
+ beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
+ beam.scale = self.target_range / 256;
+ beam.movetype = MOVETYPE_NONE;
+ beam.enemy = self.enemy;
+ beam.bot_dodge = TRUE;
+ beam.bot_dodgerating = beam.shot_dmg;
+ sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
+ self.fireflag = 1;
+
+ beam.attack_finished_single = self.attack_finished_single;
+ self.attack_finished_single = time; // + autocvar_sys_ticrate;
+
+ setattachment(beam,self.tur_head,"tag_fire");
+
+ soundat (self, trace_endpos, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ {
+ if (self.fireflag == 1)
+ {
+ if (self.tur_head.frame == 10)
+ self.tur_head.frame = 1;
+ else
+ self.tur_head.frame = self.tur_head.frame +1;
+ }
+ else if (self.fireflag == 2 )
+ {
+ self.tur_head.frame = self.tur_head.frame +1;
+ if (self.tur_head.frame == 15)
+ {
+ self.tur_head.frame = 0;
+ self.fireflag = 0;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
+
+ self.turret_firecheckfunc = turret_phaser_firecheck;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/phaser.md3");
+ precache_model ("models/turrets/phaser_beam.md3");
+ precache_sound ("turrets/phaser.wav");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_phaser(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/phaser.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define PLASMA_SETTINGS(turret)
-
-
- #ifdef SVQC
- PLASMA_SETTINGS(plasma)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA,
+/* function */ t_plasma,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasma.md3",
+/* netname */ "plasma",
+/* fullname */ _("Plasma Cannon")
+);
-
- void spawnfunc_turret_plasma() { if not(turret_initialize(TUR_PLASMA)) remove(self); }
+#else
+#ifdef SVQC
-
++void spawnfunc_turret_plasma() { if(!turret_initialize(TUR_PLASMA)) remove(self); }
+
+float t_plasma(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_minstagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
- if(teamplay)
- {
- switch(self.team)
- {
- case NUM_TEAM_1: // Red
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_2: // Blue
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_3: // Yellow
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_4: // Pink
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), self.tur_shotorg, v);
- break;
- }
- }
- else
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), self.tur_shotorg, v);
+ pointparticles(particleeffectnum("nex_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v;
++ string s;
+ v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(PLASMA_SETTINGS(plasma))
- return TRUE;
- }
++ s = strcat("TE_TEI_G3", Static_Team_ColorName_Upper(self.team));
++
++ WarpZone_TrailParticles(world, particleeffectnum(s), self.tur_shotorg, v);
++
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+ else
+ {
+ entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+ }
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 5)
+ self.tur_head.frame = 0;
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasma.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasma.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define PLASMA_DUAL_SETTINGS(turret)
-
-
- #ifdef SVQC
- PLASMA_DUAL_SETTINGS(plasma_dual)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ PLASMA_DUAL,
+/* function */ t_plasma_dual,
+/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
+/* mins,maxs */ '-32 -32 0', '32 32 64',
+/* model */ "base.md3",
+/* head_model */ "plasmad.md3",
+/* netname */ "plasma_dual",
+/* fullname */ _("Dual Plasma Cannon")
+);
-
- void spawnfunc_turret_plasma_dual() { if not(turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
+#else
+#ifdef SVQC
- if(teamplay)
- {
- switch(self.team)
- {
- case NUM_TEAM_1: // Red
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_2: // Blue
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_3: // Yellow
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), self.tur_shotorg, v);
- break;
- case NUM_TEAM_4: // Pink
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), self.tur_shotorg, v);
- break;
- }
- }
- else
- WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), self.tur_shotorg, v);
++void spawnfunc_turret_plasma_dual() { if(!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
+
+float t_plasma_dual(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ if(g_minstagib)
+ {
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+ 800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+
+ pointparticles(particleeffectnum("nex_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ // teamcolor / hit beam effect
+ vector v;
++ string s;
+ v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(PLASMA_DUAL_SETTINGS(plasma_dual))
- return TRUE;
- }
++ s = strcat("TE_TEI_G3", Static_Team_ColorName_Upper(self.team));
++
++ WarpZone_TrailParticles(world, particleeffectnum(s), self.tur_shotorg, v);
+
+ self.tur_head.frame += 1;
+ }
+ else
+ {
+ entity missile = turret_projectile("weapons/hagar_fire.wav", 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
+ missile.missile_flags = MIF_SPLASH;
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+ self.tur_head.frame += 1;
+ }
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 6)
+ self.tur_head.frame = 0;
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+ turret_do_updates(self);
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasmad.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_plasma_dual(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/plasmad.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define TESLA_SETTINGS(turret)
-
-
- #ifdef SVQC
- TESLA_SETTINGS(tesla)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ TESLA,
+/* function */ t_tesla,
+/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
+/* mins,maxs */ '-60 -60 0', '60 60 128',
+/* model */ "tesla_base.md3",
+/* head_model */ "tesla_head.md3",
+/* netname */ "tesla",
+/* fullname */ _("Tesla Coil")
+);
-
+#else
+#ifdef SVQC
- if not (turret_firecheck())
+entity toast(entity from, float range, float damage)
+{
+ entity e;
+ entity etarget = world;
+ float d,dd;
+ float r;
+
+ dd = range + 1;
+
+ e = findradius(from.origin,range);
+ while (e)
+ {
+ if ((e.railgunhit != 1) && (e != from))
+ {
+ r = turret_validate_target(self,e,self.target_validate_flags);
+ if (r > 0)
+ {
+ traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
+ if (trace_fraction == 1.0)
+ {
+ d = vlen(e.origin - from.origin);
+ if (d < dd)
+ {
+ dd = d;
+ etarget = e;
+ }
+ }
+ }
+ }
+ e = e.chain;
+ }
+
+ if (etarget)
+ {
+ te_csqc_lightningarc(from.origin,etarget.origin);
+ Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
+ etarget.railgunhit = 1;
+ }
+
+ return etarget;
+}
+
+float turret_tesla_firecheck()
+{
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+ float do_target_scan = 0;
+
+ if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+ do_target_scan = 1;
+
+ // Old target (if any) invalid?
+ if(self.target_validate_time < time)
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ self.target_validate_time = time + 0.5;
+ do_target_scan = 1;
+ }
+
+ // But never more often then g_turrets_targetscan_mindelay!
+ if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+ do_target_scan = 0;
+
+ if(do_target_scan)
+ {
+ self.enemy = turret_select_target();
+ self.target_select_time = time;
+ }
+
- void spawnfunc_turret_tesla() { if not(turret_initialize(TUR_TESLA)) remove(self); }
++ if(!turret_firecheck())
+ return 0;
+
+ if(self.enemy)
+ return 1;
+
+ return 0;
+}
+
- if not (self.active)
++void spawnfunc_turret_tesla() { if(!turret_initialize(TUR_TESLA)) remove(self); }
+
+float t_tesla(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ entity e, t;
+ float d, r, i;
+
+ d = self.shot_dmg;
+ r = self.target_range;
+ e = spawn();
+ setorigin(e,self.tur_shotorg);
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ t = toast(e,r,d);
+ remove(e);
+
+ if (t == world) return TRUE;
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.attack_finished_single = time + self.shot_refire;
+ for (i = 0; i < 10; ++i)
+ {
+ d *= 0.75;
+ r *= 0.85;
+ t = toast(t, r, d);
+ if (t == world) break;
+
+ }
+
+ e = findchainfloat(railgunhit, 1);
+ while (e)
+ {
+ e.railgunhit = 0;
+ e = e.chain;
+ }
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(TESLA_SETTINGS(tesla))
- return TRUE;
- }
++ if(!self.active)
+ {
+ self.tur_head.avelocity = '0 0 0';
+ return TRUE;
+ }
+
+ if(self.ammo < self.shot_dmg)
+ {
+ self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
+ }
+ else
+ {
+ self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
+
+ if(self.attack_finished_single > time)
+ return TRUE;
+
+ float f;
+ f = (self.ammo / self.ammo_max);
+ f = f * f;
+ if(f > random())
+ if(random() < 0.1)
+ te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
+ }
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.turret_firecheckfunc = turret_tesla_firecheck;
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
+ self.shoot_flags = TFL_SHOOT_CUSTOM;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/tesla_base.md3");
+ precache_model ("models/turrets/tesla_head.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+float t_tesla(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/tesla_base.md3");
+ precache_model ("models/turrets/tesla_head.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
--- /dev/null
-
- #define WALKER_SETTINGS(turret) \
- TUR_ADD_CVAR(turret, melee_damage) \
- TUR_ADD_CVAR(turret, melee_force) \
- TUR_ADD_CVAR(turret, melee_range) \
- TUR_ADD_CVAR(turret, rocket_damage) \
- TUR_ADD_CVAR(turret, rocket_radius) \
- TUR_ADD_CVAR(turret, rocket_force) \
- TUR_ADD_CVAR(turret, rocket_speed) \
- TUR_ADD_CVAR(turret, rocket_range) \
- TUR_ADD_CVAR(turret, rocket_range_min) \
- TUR_ADD_CVAR(turret, rocket_refire) \
- TUR_ADD_CVAR(turret, rocket_turnrate) \
- TUR_ADD_CVAR(turret, speed_stop) \
- TUR_ADD_CVAR(turret, speed_walk) \
- TUR_ADD_CVAR(turret, speed_run) \
- TUR_ADD_CVAR(turret, speed_jump) \
- TUR_ADD_CVAR(turret, speed_swim) \
- TUR_ADD_CVAR(turret, speed_roam) \
- TUR_ADD_CVAR(turret, turn) \
- TUR_ADD_CVAR(turret, turn_walk) \
- TUR_ADD_CVAR(turret, turn_strafe) \
- TUR_ADD_CVAR(turret, turn_swim) \
- TUR_ADD_CVAR(turret, turn_run)
-
-
- #ifdef SVQC
- WALKER_SETTINGS(walker)
- #endif // SVQC
+#ifdef REGISTER_TURRET
+REGISTER_TURRET(
+/* TUR_##id */ WALKER,
+/* function */ t_walker,
+/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
+/* mins,maxs */ '-70 -70 0', '70 70 95',
+/* model */ "walker_body.md3",
+/* head_model */ "walker_head_minigun.md3",
+/* netname */ "walker",
+/* fullname */ _("Walker Turret")
+);
- Damage(e, self, self, TUR_CVAR(walker, melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * TUR_CVAR(walker, melee_force));
+#else
+#ifdef SVQC
++float autocvar_g_turrets_unit_walker_melee_damage;
++float autocvar_g_turrets_unit_walker_melee_force;
++float autocvar_g_turrets_unit_walker_melee_range;
++float autocvar_g_turrets_unit_walker_rocket_damage;
++float autocvar_g_turrets_unit_walker_rocket_radius;
++float autocvar_g_turrets_unit_walker_rocket_force;
++float autocvar_g_turrets_unit_walker_rocket_speed;
++float autocvar_g_turrets_unit_walker_rocket_range;
++float autocvar_g_turrets_unit_walker_rocket_range_min;
++float autocvar_g_turrets_unit_walker_rocket_refire;
++float autocvar_g_turrets_unit_walker_rocket_turnrate;
++float autocvar_g_turrets_unit_walker_speed_stop;
++float autocvar_g_turrets_unit_walker_speed_walk;
++float autocvar_g_turrets_unit_walker_speed_run;
++float autocvar_g_turrets_unit_walker_speed_jump;
++float autocvar_g_turrets_unit_walker_speed_swim;
++float autocvar_g_turrets_unit_walker_speed_roam;
++float autocvar_g_turrets_unit_walker_turn;
++float autocvar_g_turrets_unit_walker_turn_walk;
++float autocvar_g_turrets_unit_walker_turn_strafe;
++float autocvar_g_turrets_unit_walker_turn_swim;
++float autocvar_g_turrets_unit_walker_turn_run;
+
+#define ANIM_NO 0
+#define ANIM_TURN 1
+#define ANIM_WALK 2
+#define ANIM_RUN 3
+#define ANIM_STRAFE_L 4
+#define ANIM_STRAFE_R 5
+#define ANIM_JUMP 6
+#define ANIM_LAND 7
+#define ANIM_PAIN 8
+#define ANIM_MELEE 9
+#define ANIM_SWIM 10
+#define ANIM_ROAM 11
+
+.float animflag;
+.float idletime;
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{
+ if (self.animflag == ANIM_MELEE)
+ return 0;
+
+ return turret_firecheck();
+}
+
+void walker_melee_do_dmg()
+{
+ vector where;
+ entity e;
+
+ makevectors(self.angles);
+ where = self.origin + v_forward * 128;
+
+ e = findradius(where,32);
+ while (e)
+ {
+ if (turret_validate_target(self, e, self.target_validate_flags))
+ if (e != self && e.owner != self)
- RadiusDamage (self, self.owner, TUR_CVAR(walker, rocket_damage), 0, TUR_CVAR(walker, rocket_radius), self, TUR_CVAR(walker, rocket_force), DEATH_TURRET_WALK_ROCKET, world);
++ Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
+
+ e = e.chain;
+ }
+}
+
+void walker_setnoanim()
+{
+ turrets_setframe(ANIM_NO, FALSE);
+ self.animflag = self.frame;
+}
+void walker_rocket_explode()
+{
- #define WALKER_ROCKET_MOVE movelib_move_simple(newdir, TUR_CVAR(walker, rocket_speed), TUR_CVAR(walker, rocket_turnrate)); UpdateCSQCProjectile(self)
++ RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
+ remove (self);
+}
+
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{
+ self.health = self.health - damage;
+ self.velocity = self.velocity + vforce;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
+}
+
- rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * TUR_CVAR(walker, rocket_speed);
++#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
+void walker_rocket_loop();
+void walker_rocket_think()
+{
+ vector newdir;
+ float edist;
+ float itime;
+ float m_speed;
+
+ self.nextthink = time;
+
+ edist = vlen(self.enemy.origin - self.origin);
+
+ // Simulate crude guidance
+ if (self.cnt < time)
+ {
+ if (edist < 1000)
+ self.tur_shotorg = randomvec() * min(edist, 64);
+ else
+ self.tur_shotorg = randomvec() * min(edist, 256);
+
+ self.cnt = time + 0.5;
+ }
+
+ if (edist < 128)
+ self.tur_shotorg = '0 0 0';
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if (self.shot_dmg != 1337 && random() < 0.01)
+ {
+ walker_rocket_loop();
+ return;
+ }
+
+ m_speed = vlen(self.velocity);
+
+ // Enemy dead? just keep on the current heading then.
+ if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if (self.enemy)
+ {
+ itime = max(edist / m_speed, 1);
+ newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
+ }
+ else
+ newdir = normalize(self.velocity);
+
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop3()
+{
+ vector newdir;
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.think = walker_rocket_think;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+
+ self.angles = vectoangles(self.velocity);
+}
+
+void walker_rocket_loop2()
+{
+ vector newdir;
+
+ self.nextthink = time;
+
+ if (self.max_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 100 )
+ {
+ self.tur_shotorg = self.origin - '0 0 200';
+ self.think = walker_rocket_loop3;
+ return;
+ }
+
+ newdir = steerlib_pull(self.tur_shotorg);
+ WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop()
+{
+ self.nextthink = time;
+ self.tur_shotorg = self.origin + '0 0 300';
+ self.think = walker_rocket_loop2;
+ self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{
+ entity rocket;
+
+ fixedmakevectors(self.angles);
+
+ te_explosion (org);
+
+ rocket = spawn ();
+ setorigin(rocket, org);
+
+ sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTEN_NORM);
+ setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+ rocket.classname = "walker_rocket";
+ rocket.owner = self;
+ rocket.bot_dodge = TRUE;
+ rocket.bot_dodgerating = 50;
+ rocket.takedamage = DAMAGE_YES;
+ rocket.damageforcescale = 2;
+ rocket.health = 25;
+ rocket.tur_shotorg = randomvec() * 512;
+ rocket.cnt = time + 1;
+ rocket.enemy = self.enemy;
+
+ if (random() < 0.01)
+ rocket.think = walker_rocket_loop;
+ else
+ rocket.think = walker_rocket_think;
+
+ rocket.event_damage = walker_rocket_damage;
+
+ rocket.nextthink = time;
+ rocket.movetype = MOVETYPE_FLY;
- void spawnfunc_turret_walker() { if not(turret_initialize(TUR_WALKER)) remove(self); }
++ rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
+ rocket.angles = vectoangles(rocket.velocity);
+ rocket.touch = walker_rocket_explode;
+ rocket.flags = FL_PROJECTILE;
+ rocket.solid = SOLID_BBOX;
+ rocket.max_health = time + 9;
+ rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+
+ CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
+}
+
+.vector enemy_last_loc;
+.float enemy_last_time;
+void walker_move_to(vector _target, float _dist)
+{
+ switch (self.waterlevel)
+ {
+ case WATERLEVEL_NONE:
+ if (_dist > 500)
+ self.animflag = ANIM_RUN;
+ else
+ self.animflag = ANIM_WALK;
+ case WATERLEVEL_WETFEET:
+ case WATERLEVEL_SWIMMING:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case WATERLEVEL_SUBMERGED:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = _target;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+ if(self.enemy)
+ {
+ self.enemy_last_loc = _target;
+ self.enemy_last_time = time;
+ }
+}
+
+//#define WALKER_FANCYPATHING
+
+void walker_move_path()
+{
+#ifdef WALKER_FANCYPATHING
+ // Are we close enougth to a path node to switch to the next?
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ if (self.pathcurrent.path_next == world)
+ {
+ // Path endpoint reached
+ pathlib_deletepath(self.pathcurrent.owner);
+ self.pathcurrent = world;
+
+ if (self.pathgoal)
+ {
+ if (self.pathgoal.use)
+ self.pathgoal.use();
+
+ if (self.pathgoal.enemy)
+ {
+ self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
+ self.pathgoal = self.pathgoal.enemy;
+ }
+ }
+ else
+ self.pathgoal = world;
+ }
+ else
+ self.pathcurrent = self.pathcurrent.path_next;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+ walker_move_to(self.moveto, 0);
+
+#else
+ if (vlen(self.origin - self.pathcurrent.origin) < 64)
+ self.pathcurrent = self.pathcurrent.enemy;
+
+ if(!self.pathcurrent)
+ return;
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ walker_move_to(self.moveto, 0);
+#endif
+}
+
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, self.shot_speed, 5, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
- endFireBallisticBullet();
++void spawnfunc_turret_walker() { if(!turret_initialize(TUR_WALKER)) remove(self); }
+
+float t_walker(float req)
+{
+ switch(req)
+ {
+ case TR_ATTACK:
+ {
+ sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTEN_NORM);
- if (self.tur_dist_enemy < TUR_CVAR(walker, melee_range) && self.animflag != ANIM_MELEE)
++ fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ return TRUE;
+ }
+ case TR_THINK:
+ {
+ fixedmakevectors(self.angles);
+
+ if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
+ walker_move_path();
+ else if (self.enemy == world)
+ {
+ if(self.pathcurrent)
+ walker_move_path();
+ else
+ {
+ if(self.enemy_last_time != 0)
+ {
+ if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
+ self.enemy_last_time = 0;
+ else
+ walker_move_to(self.enemy_last_loc, 0);
+ }
+ else
+ {
+ if(self.animflag != ANIM_NO)
+ {
+ traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
+
+ if(trace_fraction != 1.0)
+ self.tur_head.idletime = -1337;
+ else
+ {
+ traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
+ if(trace_fraction == 1.0)
+ self.tur_head.idletime = -1337;
+ }
+
+ if(self.tur_head.idletime == -1337)
+ {
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.idletime = 0;
+ }
+
+ self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
+ self.moveto_z = self.origin_z + 64;
+ walker_move_to(self.moveto, 0);
+ }
+
+ if(self.idletime < time)
+ {
+ if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
+ {
+ self.idletime = time + 1 + random() * 5;
+ self.moveto = self.origin;
+ self.animflag = ANIM_NO;
+ }
+ else
+ {
+ self.animflag = ANIM_WALK;
+ self.idletime = time + 4 + random() * 2;
+ self.moveto = self.origin + randomvec() * 256;
+ self.tur_head.moveto = self.moveto;
+ self.tur_head.idletime = 0;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
- self.tur_head.attack_finished_single = time + TUR_CVAR(walker, rocket_refire);
++ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
+ {
+ vector wish_angle;
+
+ wish_angle = angleofs(self, self.enemy);
+ if (self.animflag != ANIM_SWIM)
+ if (fabs(wish_angle_y) < 15)
+ {
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+ self.animflag = ANIM_MELEE;
+ }
+ }
+ else if (self.tur_head.attack_finished_single < time)
+ {
+ if(self.tur_head.shot_volly)
+ {
+ self.animflag = ANIM_NO;
+
+ self.tur_head.shot_volly = self.tur_head.shot_volly -1;
+ if(self.tur_head.shot_volly == 0)
- if (self.tur_dist_enemy > TUR_CVAR(walker, rocket_range_min))
- if (self.tur_dist_enemy < TUR_CVAR(walker, rocket_range))
++ self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
+ else
+ self.tur_head.attack_finished_single = time + 0.2;
+
+ if(self.tur_head.shot_volly > 1)
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
+ else
+ walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
+ }
+ else
+ {
- movelib_beak_simple(TUR_CVAR(walker, speed_stop));
++ if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
++ if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
+ self.tur_head.shot_volly = 4;
+ }
+ }
+ else
+ {
+ if (self.animflag != ANIM_MELEE)
+ walker_move_to(self.enemy.origin, self.tur_dist_enemy);
+ }
+ }
+
+ {
+ vector real_angle;
+ float turny = 0, turnx = 0;
+ float vz;
+
+ real_angle = vectoangles(self.steerto) - self.angles;
+ vz = self.velocity_z;
+
+ switch (self.animflag)
+ {
+ case ANIM_NO:
- turny = TUR_CVAR(walker, turn);
- movelib_beak_simple(TUR_CVAR(walker, speed_stop));
++ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_TURN:
- turny = TUR_CVAR(walker, turn_walk);
- movelib_move_simple(v_forward, TUR_CVAR(walker, speed_walk), 0.6);
++ turny = (autocvar_g_turrets_unit_walker_turn);
++ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_WALK:
- turny = TUR_CVAR(walker, turn_run);
- movelib_move_simple(v_forward, TUR_CVAR(walker, speed_run), 0.6);
++ turny = (autocvar_g_turrets_unit_walker_turn_walk);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
+ break;
+
+ case ANIM_RUN:
- turny = TUR_CVAR(walker, turn_strafe);
- movelib_move_simple(v_right * -1, TUR_CVAR(walker, speed_walk), 0.8);
++ turny = (autocvar_g_turrets_unit_walker_turn_run);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
+ break;
+
+ case ANIM_STRAFE_L:
- turny = TUR_CVAR(walker, turn_strafe);
- movelib_move_simple(v_right, TUR_CVAR(walker, speed_walk), 0.8);
++ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
++ movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_STRAFE_R:
- self.velocity += '0 0 1' * TUR_CVAR(walker, speed_jump);
++ turny = (autocvar_g_turrets_unit_walker_turn_strafe);
++ movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+ break;
+
+ case ANIM_JUMP:
- movelib_beak_simple(TUR_CVAR(walker, speed_stop));
++ self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
+ break;
+
+ case ANIM_LAND:
+ break;
+
+ case ANIM_PAIN:
+ if(self.frame != ANIM_PAIN)
+ defer(0.25, walker_setnoanim);
+
+ break;
+
+ case ANIM_MELEE:
+ if(self.frame != ANIM_MELEE)
+ {
+ defer(0.41, walker_setnoanim);
+ defer(0.21, walker_melee_do_dmg);
+ }
+
- turny = TUR_CVAR(walker, turn_swim);
- turnx = TUR_CVAR(walker, turn_swim);
++ movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+ break;
+
+ case ANIM_SWIM:
- movelib_move_simple(v_forward, TUR_CVAR(walker, speed_swim), 0.3);
++ turny = (autocvar_g_turrets_unit_walker_turn_swim);
++ turnx = (autocvar_g_turrets_unit_walker_turn_swim);
+
+ self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
- turny = TUR_CVAR(walker, turn_walk);
- movelib_move_simple(v_forward ,TUR_CVAR(walker, speed_roam), 0.5);
++ movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
+ vz = self.velocity_z + sin(time * 4) * 8;
+ break;
+
+ case ANIM_ROAM:
-
- if (autocvar_g_antilag_bullets)
- self.turret_flags |= TUR_FLAG_HITSCAN;
- else
- self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
++ turny = (autocvar_g_turrets_unit_walker_turn_walk);
++ movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
+ break;
+ }
+
+ if(turny)
+ {
+ turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
+ self.angles_y += turny;
+ }
+
+ if(turnx)
+ {
+ turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
+ self.angles_x += turnx;
+ }
+
+ self.velocity_z = vz;
+ }
+
+
+ if(self.origin != self.oldorigin)
+ self.SendFlags |= TNSF_MOVE;
+
+ self.oldorigin = self.origin;
+ turrets_setframe(self.animflag, FALSE);
+
+ return TRUE;
+ }
+ case TR_DEATH:
+ {
+#ifdef WALKER_FANCYPATHING
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+#endif
+ self.pathcurrent = world;
+
+ return TRUE;
+ }
+ case TR_SETUP:
+ {
+ self.ticrate = 0.05;
+
+ entity e;
+
+ // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
+ if(self.movetype == MOVETYPE_WALK)
+ {
+ if(self.pos1)
+ setorigin(self, self.pos1);
+ if(self.pos2)
+ self.angles = self.pos2;
+ }
+
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+ self.aim_flags = TFL_AIM_LEAD;
- }
- case TR_CONFIG:
- {
- TUR_CONFIG_SETTINGS(WALKER_SETTINGS(walker))
- return TRUE;
++ self.turret_flags |= TUR_FLAG_HITSCAN;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.iscreature = TRUE;
+ self.teleportable = TELEPORT_NORMAL;
+ self.damagedbycontents = TRUE;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+ if(self.movetype != MOVETYPE_WALK)
+ {
+ setorigin(self, self.origin);
+ tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
+ setorigin(self, trace_endpos + '0 0 4');
+ self.pos1 = self.origin;
+ self.pos2 = self.angles;
+ }
+ self.movetype = MOVETYPE_WALK;
+ self.idle_aim = '0 0 0';
+ self.turret_firecheckfunc = walker_firecheck;
+
+ if (self.target != "")
+ {
+ e = find(world, targetname, self.target);
+ if (!e)
+ {
+ dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ {
+#ifdef WALKER_FANCYPATHING
+ self.pathcurrent = WALKER_PATH(self.origin, e.origin);
+ self.pathgoal = e;
+#else
+ self.pathcurrent = e;
+#endif
+ }
+ }
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/walker_body.md3");
+ precache_model ("models/turrets/walker_head_minigun.md3");
+ precache_model ("models/turrets/rocket.md3");
+ precache_sound ("weapons/rocket_impact.wav");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // SVQC
+#ifdef CSQC
+
+void walker_draw()
+{
+ float dt;
+
+ dt = time - self.move_time;
+ self.move_time = time;
+ if(dt <= 0)
+ return;
+
+ fixedmakevectors(self.angles);
+ movelib_groundalign4point(300, 100, 0.25, 45);
+ setorigin(self, self.origin + self.velocity * dt);
+ self.tur_head.angles += dt * self.tur_head.move_avelocity;
+ self.angles_y = self.move_angles_y;
+
+ if (self.health < 127)
+ if(random() < 0.15)
+ te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+float t_walker(float req)
+{
+ switch(req)
+ {
+ case TR_SETUP:
+ {
+ self.gravity = 1;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.move_movetype = MOVETYPE_BOUNCE;
+ self.move_origin = self.origin;
+ self.move_time = time;
+ self.draw = walker_draw;
+
+ return TRUE;
+ }
+ case TR_PRECACHE:
+ {
+ precache_model ("models/turrets/walker_body.md3");
+ precache_model ("models/turrets/walker_head_minigun.md3");
+ return TRUE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // CSQC
+#endif // REGISTER_TURRET
#define autocvar_fraglimit_override cvar("fraglimit_override")
float autocvar_g_allow_oldnexbeam;
float autocvar_g_antilag;
- float autocvar_g_antilag_bullets;
float autocvar_g_antilag_nudge;
- float autocvar_g_arena_maxspawned;
- float autocvar_g_arena_point_leadlimit;
- float autocvar_g_arena_point_limit;
- float autocvar_g_arena_roundbased;
- float autocvar_g_arena_round_timelimit;
- float autocvar_g_arena_warmup;
float autocvar_g_balance_armor_blockpercent;
float autocvar_g_balance_armor_limit;
float autocvar_g_balance_armor_regen;
float autocvar_g_balance_rifle_bursttime;
float autocvar_g_balance_rifle_primary_ammo;
float autocvar_g_balance_rifle_primary_animtime;
- float autocvar_g_balance_rifle_primary_bulletconstant;
float autocvar_g_balance_rifle_primary_bullethail;
float autocvar_g_balance_rifle_primary_burstcost;
float autocvar_g_balance_rifle_primary_damage;
float autocvar_g_balance_rifle_primary_force;
- float autocvar_g_balance_rifle_primary_lifetime;
float autocvar_g_balance_rifle_primary_refire;
float autocvar_g_balance_rifle_primary_shots;
- float autocvar_g_balance_rifle_primary_speed;
+ float autocvar_g_balance_rifle_primary_solidpenetration;
float autocvar_g_balance_rifle_primary_spread;
float autocvar_g_balance_rifle_primary_tracer;
float autocvar_g_balance_rifle_secondary;
float autocvar_g_balance_rifle_secondary_ammo;
float autocvar_g_balance_rifle_secondary_animtime;
- float autocvar_g_balance_rifle_secondary_bulletconstant;
float autocvar_g_balance_rifle_secondary_bullethail;
float autocvar_g_balance_rifle_secondary_burstcost;
float autocvar_g_balance_rifle_secondary_damage;
float autocvar_g_balance_rifle_secondary_force;
- float autocvar_g_balance_rifle_secondary_lifetime;
float autocvar_g_balance_rifle_secondary_reload;
float autocvar_g_balance_rifle_secondary_refire;
float autocvar_g_balance_rifle_secondary_shots;
- float autocvar_g_balance_rifle_secondary_speed;
+ float autocvar_g_balance_rifle_secondary_solidpenetration;
float autocvar_g_balance_rifle_secondary_spread;
float autocvar_g_balance_rifle_secondary_tracer;
float autocvar_g_balance_rifle_reload_ammo;
float autocvar_g_balance_health_rot;
float autocvar_g_balance_health_rotlinear;
float autocvar_g_balance_health_rotstable;
- float autocvar_g_balance_health_start;
float autocvar_g_balance_hlac_primary_ammo;
float autocvar_g_balance_hlac_primary_animtime;
float autocvar_g_balance_hlac_primary_damage;
float autocvar_g_balance_selfdamagepercent;
float autocvar_g_balance_shotgun_primary_ammo;
float autocvar_g_balance_shotgun_primary_animtime;
- float autocvar_g_balance_shotgun_primary_bulletconstant;
float autocvar_g_balance_shotgun_primary_bullets;
float autocvar_g_balance_shotgun_primary_damage;
float autocvar_g_balance_shotgun_primary_force;
float autocvar_g_balance_shotgun_primary_refire;
- float autocvar_g_balance_shotgun_primary_speed;
+ float autocvar_g_balance_shotgun_primary_solidpenetration;
float autocvar_g_balance_shotgun_primary_spread;
float autocvar_g_balance_shotgun_secondary;
float autocvar_g_balance_shotgun_secondary_animtime;
float autocvar_g_balance_tuba_force;
float autocvar_g_balance_tuba_radius;
float autocvar_g_balance_tuba_refire;
- float autocvar_g_balance_uzi_bulletconstant;
float autocvar_g_balance_uzi_burst;
float autocvar_g_balance_uzi_burst_ammo;
float autocvar_g_balance_uzi_burst_animtime;
float autocvar_g_balance_uzi_first_refire;
float autocvar_g_balance_uzi_first_spread;
float autocvar_g_balance_uzi_mode;
- float autocvar_g_balance_uzi_speed;
+ float autocvar_g_balance_uzi_solidpenetration;
float autocvar_g_balance_uzi_spread_add;
float autocvar_g_balance_uzi_spread_max;
float autocvar_g_balance_uzi_spread_min;
float autocvar_g_balance_uzi_reload_time;
float autocvar_g_ballistics_density_corpse;
float autocvar_g_ballistics_density_player;
- float autocvar_g_ballistics_materialconstant;
float autocvar_g_ballistics_mindistance;
float autocvar_g_ban_default_bantime;
float autocvar_g_ban_default_masksize;
float autocvar_g_ca_spectate_enemies;
float autocvar_g_ca_teams;
float autocvar_g_ca_teams_override;
+ float autocvar_g_ca_team_spawns;
float autocvar_g_ca_warmup;
float autocvar_g_campaign;
#define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
float autocvar_g_chat_tellprivacy;
float autocvar_g_ctf_allow_vehicle_carry;
float autocvar_g_ctf_allow_vehicle_touch;
+ float autocvar_g_ctf_allow_monster_touch;
float autocvar_g_ctf_throw;
float autocvar_g_ctf_throw_angle_max;
float autocvar_g_ctf_throw_angle_min;
float autocvar_g_freezetag_round_timelimit;
float autocvar_g_freezetag_teams;
float autocvar_g_freezetag_teams_override;
+ float autocvar_g_freezetag_team_spawns;
float autocvar_g_freezetag_warmup;
#define autocvar_g_friendlyfire cvar("g_friendlyfire")
#define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
float autocvar_g_race_qualifying_timelimit;
float autocvar_g_race_qualifying_timelimit_override;
float autocvar_g_race_teams;
- float autocvar_g_respawn_delay;
+ float autocvar_g_respawn_delay_small;
+ float autocvar_g_respawn_delay_small_count;
+ float autocvar_g_respawn_delay_large;
+ float autocvar_g_respawn_delay_large_count;
+ float autocvar_g_respawn_delay_max;
float autocvar_g_respawn_ghosts;
float autocvar_g_respawn_ghosts_maxtime;
float autocvar_g_respawn_ghosts_speed;
float autocvar_g_turrets_reloadcvars;
float autocvar_g_turrets_targetscan_maxdelay;
float autocvar_g_turrets_targetscan_mindelay;
-float autocvar_g_turrets_unit_ewheel_speed_fast;
-float autocvar_g_turrets_unit_ewheel_speed_slow;
-float autocvar_g_turrets_unit_ewheel_speed_slower;
-float autocvar_g_turrets_unit_ewheel_speed_stop;
-float autocvar_g_turrets_unit_ewheel_turnrate;
-float autocvar_g_turrets_unit_hellion_std_shot_speed_gain;
-float autocvar_g_turrets_unit_hellion_std_shot_speed_max;
-float autocvar_g_turrets_unit_hk_std_shot_speed;
-float autocvar_g_turrets_unit_hk_std_shot_speed_accel;
-float autocvar_g_turrets_unit_hk_std_shot_speed_accel2;
-float autocvar_g_turrets_unit_hk_std_shot_speed_decel;
-float autocvar_g_turrets_unit_hk_std_shot_speed_max;
-float autocvar_g_turrets_unit_hk_std_shot_speed_turnrate;
-float autocvar_g_turrets_unit_walker_speed_jump;
-float autocvar_g_turrets_unit_walker_speed_roam;
-float autocvar_g_turrets_unit_walker_speed_run;
-float autocvar_g_turrets_unit_walker_speed_stop;
-float autocvar_g_turrets_unit_walker_speed_swim;
-float autocvar_g_turrets_unit_walker_speed_walk;
-float autocvar_g_turrets_unit_walker_std_meele_dmg;
-float autocvar_g_turrets_unit_walker_std_meele_force;
-float autocvar_g_turrets_unit_walker_std_meele_range;
-float autocvar_g_turrets_unit_walker_std_rocket_dmg;
-float autocvar_g_turrets_unit_walker_std_rocket_force;
-float autocvar_g_turrets_unit_walker_std_rocket_radius;
-float autocvar_g_turrets_unit_walker_std_rocket_refire;
-float autocvar_g_turrets_unit_walker_std_rocket_speed;
-float autocvar_g_turrets_unit_walker_std_rocket_turnrate;
-float autocvar_g_turrets_unit_walker_std_rockets_range;
-float autocvar_g_turrets_unit_walker_std_rockets_range_min;
-float autocvar_g_turrets_unit_walker_turn;
-float autocvar_g_turrets_unit_walker_turn_walk;
-float autocvar_g_turrets_unit_walker_turn_run;
-float autocvar_g_turrets_unit_walker_turn_strafe;
-float autocvar_g_turrets_unit_walker_turn_swim;
float autocvar_g_use_ammunition;
float autocvar_g_waypointeditor;
float autocvar_g_waypointeditor_auto;
float autocvar_g_physical_items;
float autocvar_g_physical_items_damageforcescale;
float autocvar_g_physical_items_reset;
+ float autocvar_g_monsters;
+ float autocvar_g_monsters_edit;
+ float autocvar_g_monsters_think_delay;
+ float autocvar_g_monsters_max;
+ float autocvar_g_monsters_max_perplayer;
+ float autocvar_g_monsters_target_range;
+ float autocvar_g_monsters_target_infront;
+ float autocvar_g_monsters_attack_range;
+ float autocvar_g_monsters_score_kill;
+ float autocvar_g_monsters_score_spawned;
+ float autocvar_g_monsters_typefrag;
+ float autocvar_g_monsters_owners;
+ float autocvar_g_monsters_miniboss_chance;
+ float autocvar_g_monsters_miniboss_healthboost;
+ float autocvar_g_monsters_drop_time;
+ float autocvar_g_monsters_spawnshieldtime;
+ float autocvar_g_monsters_teams;
+ float autocvar_g_monsters_respawn_delay;
+ float autocvar_g_monsters_respawn;
+ float autocvar_g_monsters_armor_blockpercent;
float autocvar_g_touchexplode_radius;
float autocvar_g_touchexplode_damage;
float autocvar_g_touchexplode_edgedamage;
float autocvar_g_touchexplode_force;
+ float autocvar_g_invasion_round_timelimit;
+ #define autocvar_g_invasion_round_limit cvar("g_invasion_round_limit")
+ float autocvar_g_invasion_warmup;
+ float autocvar_g_invasion_monster_count;
+ float autocvar_g_invasion_zombies_only;
+ float autocvar_g_invasion_spawn_delay;
#define autocvar_g_bloodloss cvar("g_bloodloss")
float autocvar_g_random_gravity_negative_chance;
float autocvar_g_random_gravity_min;
float autocvar_g_campcheck_distance;
float autocvar_g_campcheck_interval;
float autocvar_g_jump_grunt;
+ float autocvar_g_spawn_near_teammate_distance;
+ float autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
+ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+ float autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
}
if(warmup_stage)
- GiveFrags_randomweapons.weapons = warmup_start_weapons;
+ GiveFrags_randomweapons.weapons = WARMUP_START_WEAPONS;
else
GiveFrags_randomweapons.weapons = start_weapons;
}
// after a frag, choose another random weapon set
- if not(attacker.weapons & WepSet_FromWeapon(attacker.weapon))
+ if (!(attacker.weapons & WepSet_FromWeapon(attacker.weapon)))
W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
}
if(DEATH_ISSPECIAL(deathtype))
{
entity deathent = deathtypes[(deathtype - DT_FIRST)];
- if not(deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
+ if (!deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
if(murder)
{
}
else
{
- dprint(sprintf(
+ dprintf(
"Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %d!\n",
deathtype,
death_weapon
- ));
+ );
}
return TRUE;
void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
{
// Sanity check
- if not(IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
+ if (!IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
// Declarations
float notif_firstblood = FALSE;
)
);
#endif
-
+
// =======
// SUICIDE
// =======
Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
break;
}
-
+
default:
{
Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
}
}
}
- else if not(Obituary_WeaponDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0))
+ else if (!Obituary_WeaponDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0))
{
backtrace("SUICIDE: what the hell happened here?\n");
return;
GiveFrags(attacker, targ, -1, deathtype);
attacker.killcount = 0;
-
+
Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker.netname);
Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(targ.team, INFO_DEATH_TEAMKILL_), targ.netname, attacker.netname, deathlocation, targ.killcount);
);
}
- if not(Obituary_WeaponDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker))
+ if (!Obituary_WeaponDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker))
Obituary_SpecialDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker, 0);
}
}
0);
break;
}
-
+
default:
{
Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
{
float mirrordamage;
float mirrorforce;
- float complainteamdamage = 0;
+ float complainteamdamage = 0;
entity attacker_save;
mirrordamage = 0;
mirrorforce = 0;
// exit the vehicle before killing (fixes a crash)
if(IS_PLAYER(targ) && targ.vehicle)
vehicles_exit(VHEF_RELESE);
-
+
// These are ALWAYS lethal
// No damage modification here
// Instead, prepare the victim for his death...
}
}
- if not(DEATH_ISSPECIAL(deathtype))
+ if (!DEATH_ISSPECIAL(deathtype))
{
damage *= g_weapondamagefactor;
mirrordamage *= g_weapondamagefactor;
force = force * g_weaponforcefactor;
mirrorforce *= g_weaponforcefactor;
}
-
+
// should this be changed at all? If so, in what way?
frag_attacker = attacker;
frag_target = targ;
frag_damage = damage;
frag_force = force;
- frag_deathtype = deathtype;
+ frag_deathtype = deathtype;
frag_mirrordamage = mirrordamage;
MUTATOR_CALLHOOK(PlayerDamage_Calculate);
damage = frag_damage;
mirrordamage = frag_mirrordamage;
force = frag_force;
-
- if not(g_minstagib)
+
+ if (!g_minstagib)
{
// apply strength multiplier
if (attacker.items & IT_STRENGTH)
else
victim = targ;
- if(IS_PLAYER(victim) || victim.turret_flags & TUR_FLAG_ISTURRET)
- if(IS_PLAYER(victim) || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET || victim.flags & FL_MONSTER)
++ if(IS_PLAYER(victim) || ((victim.turret_flags & TUR_FLAG_ISTURRET) && victim.active == ACTIVE_ACTIVE) || (victim.flags & FL_MONSTER))
{
if(DIFF_TEAM(victim, attacker))
{
damage_goodhits += 1;
damage_gooddamage += damage;
- if not(DEATH_ISSPECIAL(deathtype))
+ if (!DEATH_ISSPECIAL(deathtype))
{
if(IS_PLAYER(targ)) // don't do this for vehicles
if(IsFlying(victim))
mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
if(autocvar_g_throughfloor_debug)
- print(sprintf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f));
+ printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
total = 0.25 * pow(max(mininv_f, mininv_d), 2);
if(autocvar_g_throughfloor_debug)
- print(sprintf(" steps=%f", total));
+ printf(" steps=%f", total);
if (IS_PLAYER(targ))
total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
if(autocvar_g_throughfloor_debug)
- print(sprintf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total))));
+ printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
for(c = 0; c < total; ++c)
{
force = force * a;
if(autocvar_g_throughfloor_debug)
- print(sprintf(" D=%f F=%f\n", finaldmg, vlen(force)));
+ printf(" D=%f F=%f\n", finaldmg, vlen(force));
}
// laser force adjustments :P
if(maxtime > mintime || maxdps > mindps)
{
// Constraints:
-
+
// damage we have right now
mindamage = mindps * mintime;
float t, d, hi, ty;
entity o;
- if not(Fire_IsBurning(e))
+ if (!Fire_IsBurning(e))
return;
for(t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
}
e.fire_hitsound = TRUE;
- if not(IS_INDEPENDENT_PLAYER(e))
+ if (!IS_INDEPENDENT_PLAYER(e))
FOR_EACH_PLAYER(other) if(e != other)
{
if(IS_PLAYER(other))
if(other.deadflag == DEAD_NO)
- if not(IS_INDEPENDENT_PLAYER(other))
+ if (!IS_INDEPENDENT_PLAYER(other))
if(boxesoverlap(e.absmin, e.absmax, other.absmin, other.absmax))
{
t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
// mapinfo
BADCVAR("fraglimit");
- BADCVAR("g_arena");
BADCVAR("g_assault");
BADCVAR("g_ca");
BADCVAR("g_ca_teams");
// does nothing visible
BADCVAR("captureleadlimit_override");
- BADCVAR("g_arena_point_leadlimit");
BADCVAR("g_balance_kill_delay");
BADCVAR("g_ca_point_leadlimit");
BADCVAR("g_ctf_captimerecord_always");
BADCVAR("g_nix");
BADCVAR("g_grappling_hook");
BADCVAR("g_jetpack");
-
+
#undef BADPREFIX
#undef BADCVAR
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
+ CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+ CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
+ CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
+ // monsters
+ addstat(STAT_MONSTERS_TOTAL, AS_FLOAT, stat_monsters_total);
+ addstat(STAT_MONSTERS_KILLED, AS_FLOAT, stat_monsters_killed);
+
// misc
addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
// set up information replies for clients and server to use
maplist_reply = strzone(getmaplist());
lsmaps_reply = strzone(getlsmaps());
+ monsterlist_reply = strzone(getmonsterlist());
for(i = 0; i < 10; ++i)
{
s = getrecords(i);
{
s = strcat(":player:see-labels:", GetPlayerScoreString(other, 0), ":");
s = strcat(s, ftos(rint(time - other.jointime)), ":");
- if(IS_PLAYER(other) || g_arena || other.caplayer == 1 || g_lms)
+ if(IS_PLAYER(other) || other.caplayer == 1 || g_lms)
s = strcat(s, ftos(other.team), ":");
else
s = strcat(s, "spectator:");
PlayerStats_AddGlobalInfo(e);
PlayerStats_Shutdown();
WeaponStats_Shutdown();
-
+
Kill_Notification(NOTIF_ALL, world, MSG_CENTER, 0); // kill all centerprints now
if(autocvar_sv_eventlog)
if(WinningConditionHelper_zeroisworst)
leadlimit = 0; // not supported in this mode
- if(g_dm || g_tdm || g_arena || g_ca || (g_race && !g_race_qualifying) || g_nexball)
+ if(g_dm || g_tdm || g_ca || g_freezetag || (g_race && !g_race_qualifying) || g_nexball)
// these modes always score in increments of 1, thus this makes sense
{
if(leaderfrags != WinningConditionHelper_topscore)
if(mapvote_initialized)
return "Can't suggest - voting is already in progress!";
m = MapInfo_FixName(m);
- if not(m)
+ if (!m)
return "The map you suggested is not available on this server.";
if(!autocvar_g_maplist_votable_suggestions_override_mostrecent)
if(Map_IsRecent(m))
#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v))
- #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if not(IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
+ #define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if (!IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v))
+ #define FOR_EACH_MONSTER(v) for(v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
+
#define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
// copies a string to a tempstring (so one can strunzone it)
WepSet warmup_start_weapons;
WepSet warmup_start_weapons_default;
WepSet warmup_start_weapons_defaultmask;
+ #define WARMUP_START_WEAPONS ((g_warmup_allguns == 1) ? (warmup_start_weapons & (weaponsInMap | start_weapons)) : warmup_start_weapons)
float warmup_start_ammo_shells;
float warmup_start_ammo_nails;
float warmup_start_ammo_rockets;
d = 0; // weapon is set a few lines later
else
d = (i == WEP_LASER || i == WEP_SHOTGUN);
-
+
if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
d |= (i == WEP_HOOK);
if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns
d = 0;
var float t = cvar(strcat(cvarprefix, weaponinfo.netname));
-
+
//print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n"));
-
+
// bit order in t:
// 1: want or not
// 2: is default?
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
e = get_weaponinfo(j);
- if not(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
+ if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
g_weaponarena_weapons |= WepSet_FromWeapon(j);
}
}
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
{
e = get_weaponinfo(j);
- if not(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
+ if (!(e.spawnflags & WEP_FLAG_MUTATORBLOCKED))
if (e.spawnflags & WEP_FLAG_NORMAL)
g_weaponarena_weapons |= WepSet_FromWeapon(j);
}
if(!cvar("g_use_ammunition"))
start_items |= IT_UNLIMITED_AMMO;
-
+
if(start_items & IT_UNLIMITED_WEAPON_AMMO)
{
start_ammo_rockets = 999;
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- float w = want_weapon("g_start_weapon_", e, cvar("g_warmup_allguns"));
+ float w = want_weapon("g_start_weapon_", e, g_warmup_allguns);
if(w & 1)
warmup_start_weapons |= WepSet_FromWeapon(i);
if(w & 2)
warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
}
+ WepSet precache_weapons = start_weapons;
+ if (g_warmup_allguns != 1)
+ precache_weapons |= warmup_start_weapons;
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- if((start_weapons | warmup_start_weapons) & WepSet_FromWeapon(i))
+ if(precache_weapons & WepSet_FromWeapon(i))
weapon_action(i, WR_PRECACHE);
}
// load mutators
#define CHECK_MUTATOR_ADD(mut_cvar,mut_name,dependence) \
{ if(cvar(mut_cvar) && dependence) { MUTATOR_ADD(mut_name); } }
-
+
CHECK_MUTATOR_ADD("g_dodging", mutator_dodging, 1);
- CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, 1);
+ CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, teamplay);
CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
CHECK_MUTATOR_ADD("g_touchexplode", mutator_touchexplode, 1);
CHECK_MUTATOR_ADD("g_minstagib", mutator_minstagib, 1);
CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1);
CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
CHECK_MUTATOR_ADD("g_campcheck", mutator_campcheck, 1);
-
+
#undef CHECK_MUTATOR_ADD
-
+
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
g_bugrigs_steer = cvar("g_bugrigs_steer");
-
+
g_minstagib = cvar("g_minstagib");
sv_clones = cvar("sv_clones");
g_warmup_allguns = cvar("g_warmup_allguns");
g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
- if ((g_race && g_race_qualifying == 2) || g_arena || g_assault || cvar("g_campaign"))
+ if ((g_race && g_race_qualifying == 2) || g_assault || cvar("g_campaign"))
warmup_stage = 0; // these modes cannot work together, sorry
g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
if(!g_weapon_stay)
g_weapon_stay = cvar("g_weapon_stay");
- if not(warmup_stage)
+ if (!warmup_stage)
game_starttime = time + cvar("g_start_delay");
readplayerstartcvars();
// gamemode related things
precache_model ("models/misc/chatbubble.spr");
-#ifdef TTURRETS_ENABLED
- if (autocvar_g_turrets)
- turrets_precash();
-#endif
-
// Precache all player models if desired
if (autocvar_sv_precacheplayermodels)
{
void adaptor_think2use_hittype_splash() // for timed projectile detonation
{
- if not(self.flags & FL_ONGROUND) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
+ if(!(self.flags & FL_ONGROUND)) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
self.projectiledeathtype |= HITTYPE_SPLASH;
adaptor_think2use();
}
if(trace_dphitcontents == 0)
{
//dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
- dprint(sprintf("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Profectile will self-destruct. (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.origin)));
+ dprintf("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Profectile will self-destruct. (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.origin));
checkclient();
}
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
db_put(ServerProgsDB, strcat("uid2name", myuid), "");
}
}
-
+
if(s == "")
s = "^1Unregistered Player";
return s;
return FALSE;
}
- float zcurveparticles_effectno;
- vector zcurveparticles_start;
- float zcurveparticles_spd;
-
- void endzcurveparticles()
- {
- if(zcurveparticles_effectno)
- {
- // terminator
- WriteShort(MSG_BROADCAST, zcurveparticles_spd | 0x8000);
- }
- zcurveparticles_effectno = 0;
- }
-
- void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
- {
- spd = bound(0, floor(spd / 16), 32767);
- if(effectno != zcurveparticles_effectno || start != zcurveparticles_start)
- {
- endzcurveparticles();
- WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
- WriteShort(MSG_BROADCAST, effectno);
- WriteCoord(MSG_BROADCAST, start_x);
- WriteCoord(MSG_BROADCAST, start_y);
- WriteCoord(MSG_BROADCAST, start_z);
- zcurveparticles_effectno = effectno;
- zcurveparticles_start = start;
- }
- else
- WriteShort(MSG_BROADCAST, zcurveparticles_spd);
- WriteCoord(MSG_BROADCAST, end_x);
- WriteCoord(MSG_BROADCAST, end_y);
- WriteCoord(MSG_BROADCAST, end_z);
- WriteCoord(MSG_BROADCAST, end_dz);
- zcurveparticles_spd = spd;
- }
-
- void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
- {
- float end_dz;
- vector vecxy, velxy;
-
- vecxy = end - start;
- vecxy_z = 0;
- velxy = vel;
- velxy_z = 0;
-
- if (vlen(velxy) < 0.000001 * fabs(vel_z))
- {
- endzcurveparticles();
- trailparticles(world, effectno, start, end);
- return;
- }
-
- end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
- zcurveparticles(effectno, start, end, end_dz, vlen(vel));
- }
-
void write_recordmarker(entity pl, float tstart, float dt)
{
GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
float randombit(float bits)
{
- if not(bits & (bits-1)) // this ONLY holds for powers of two!
+ if(!(bits & (bits-1))) // this ONLY holds for powers of two!
return bits;
float n, f, b, r;
#else
string cvar_string_normal(string n)
{
- if not(cvar_type(n) & 1)
+ if (!(cvar_type(n) & 1))
backtrace(strcat("Attempt to access undefined cvar: ", n));
return builtin_cvar_string(n);
}
activator = self;
SUB_UseTargets();
-#ifdef TTURRETS_ENABLED
entity ent, oldself;
//(Re)spawn all turrets
self = ent;
// Dubbles as teamchange
- turret_stdproc_respawn();
+ turret_respawn();
ent = find(ent, classname, "turret_main");
}
self = oldself;
-#endif
}
void assault_wall_think()
// trigger new round
// reset objectives, toggle spawnpoints, reset triggers, ...
- void vehicles_clearrturn();
- void vehicles_spawn();
void assault_new_round()
{
- entity oldself;
- //bprint("ASSAULT: new round\n");
-
- oldself = self;
- // Eject players from vehicles
- FOR_EACH_PLAYER(self)
- {
- if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
- }
-
- self = findchainflags(vehicle_flags, VHF_ISVEHICLE);
- while(self)
- {
- vehicles_clearrturn();
- vehicles_spawn();
- self = self.chain;
- }
-
- self = oldself;
-
// up round counter
self.winning = self.winning + 1;
// spawnfuncs
void spawnfunc_info_player_attacker()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
self.team = NUM_TEAM_1; // red, gets swapped every round
spawnfunc_info_player_deathmatch();
}
void spawnfunc_info_player_defender()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
self.team = NUM_TEAM_2; // blue, gets swapped every round
spawnfunc_info_player_deathmatch();
}
void spawnfunc_target_objective()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
self.classname = "target_objective";
self.use = assault_objective_use;
assault_objective_reset();
void spawnfunc_target_objective_decrease()
{
- if not(g_assault) { remove(self); return; }
+ if (!g_assault) { remove(self); return; }
self.classname = "target_objective_decrease";
// destructible walls that can be used to trigger target_objective_decrease
void spawnfunc_func_assault_destructible()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
self.spawnflags = 3;
self.classname = "func_assault_destructible";
-
+
if(assault_attacker_team == NUM_TEAM_1)
self.team = NUM_TEAM_2;
else
void spawnfunc_func_assault_wall()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
self.classname = "func_assault_wall";
self.mdl = self.model;
setmodel(self, self.mdl);
void spawnfunc_target_assault_roundend()
{
- if not(g_assault) { remove(self); return; }
+ if (!g_assault) { remove(self); return; }
self.winning = 0; // round not yet won by attackers
self.classname = "target_assault_roundend";
void spawnfunc_target_assault_roundstart()
{
- if not(g_assault) { remove(self); return; }
-
+ if (!g_assault) { remove(self); return; }
+
assault_attacker_team = NUM_TEAM_1;
self.classname = "target_assault_roundstart";
self.use = assault_roundstart_use;
if (ad.target == "")
continue;
- if not(ad.bot_attack)
+ if (!ad.bot_attack)
continue;
found = FALSE;
centerprint(self, "You are attacking!");
else
centerprint(self, "You are defending!");
-
+
return FALSE;
}
MUTATOR_HOOKFUNCTION(assault_TurretSpawn)
{
- if not (self.team)
+ if (!self.team)
self.team = 14;
return FALSE;
MUTATOR_HOOK(TurretSpawn, assault_TurretSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(VehicleSpawn, assault_VehicleSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(HavocBot_ChooseRule, assault_BotRoles, CBC_ORDER_ANY);
-
+
MUTATOR_ONADD
{
if(time > 1) // game loads at time 1
d = d + 1;
e = e.chain;
}
-
+
if(autocvar_g_campaign && autocvar__campaign_testrun)
d = d * self.max_health;
else
d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
-
+
Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
}
else if (overtime_msg_time)
vector org;
float i;
- if not (self.count)
+ if (!self.count)
self.count = 40;
// White shockwave
#endif
self.lasthealth = self.health;
}
- else if not(warmup_stage)
+ else if (!warmup_stage)
{
if (attacker == self)
bprint(Team_ColoredFullName(self.team), " generator spontaneously exploded due to overtime!\n");
precache_sound("onslaught/electricity_explode.wav");
if (!self.team)
objerror("team must be set");
-
+
if(self.team == NUM_TEAM_1)
ons_red_generator = self;
if(self.team == NUM_TEAM_2)
ons_blue_generator = self;
-
+
self.team_saved = self.team;
self.colormap = 1024 + (self.team - 1) * 17;
self.solid = SOLID_BBOX;
waypoint_spawnforitem(self);
onslaught_updatelinks();
-
+
self.reset = onslaught_generator_reset;
}
float _friendly_count = 0;
float _dist;
entity _player;
-
+
FOR_EACH_PLAYER(_player)
{
if(!_player.deadflag)
a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
if(!a)
return;
-
+
self.health = self.health + self.count;
if (self.health >= self.max_health)
{
entity e;
float a;
- if not(IS_PLAYER(other))
+ if (!IS_PLAYER(other))
return;
a = onslaught_controlpoint_attackable(self, other.team);
if(a != 2 && a != 4)
onslaught_updatelinks();
}
+ void onslaught_controlpoint_think()
+ {
+ self.nextthink = time;
+ CSQCMODEL_AUTOUPDATE();
+ }
+
void onslaught_controlpoint_reset()
{
if(self.goalentity && self.goalentity != world)
self.isshielded = TRUE;
self.enemy.solid = SOLID_NOT;
self.enemy.colormap = self.colormap;
- self.think = self.enemy.think = func_null;
- self.nextthink = 0; // don't like func_null :P
+ self.think = onslaught_controlpoint_think;
+ self.enemy.think = func_null;
+ self.nextthink = time; // don't like func_null :P
setmodel(self, "models/onslaught/controlpoint_pad.md3");
//setsize(self, '-32 -32 0', '32 32 8');
activator = self;
SUB_UseTargets(); // to reset the structures, playerspawns etc.
+
+ CSQCMODEL_AUTOUPDATE();
}
/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
self.enemy.colormap = self.colormap;
waypoint_spawnforitem(self);
+
+ self.think = onslaught_controlpoint_think;
+ self.nextthink = time;
WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
self.reset = onslaught_controlpoint_reset;
+
+ CSQCMODEL_AUTOINIT();
}
float onslaught_link_send(entity to, float sendflags)
MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
{
-
+
/*
float _neer_home = (random() > 0.5 ? TRUE : FALSE);
-
+
RandomSelection_Init();
-
+
if(self.team == NUM_TEAM_1)
RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
-
+
if(self.team == NUM_TEAM_2)
RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
-
+
entity _cp = findchain(classname, "onslaught_controlpoint"):
while _cp;
{
- if(_cp.team == self.team)
+ if(_cp.team == self.team)
RandomSelection_Add(_cp, 0, string_null, 1, 1);
-
+
_cp = _cp.chain;
}
}
else if(self.team == spawn_spot.team)
spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
-
+
*/
-
+
return 0;
}
{
if(!autocvar_g_onslaught_spawn_at_controlpoints)
return 0;
-
+
if(random() < 0.5) // 50/50 chane to use default spawnsystem.
return 0;
-
+
float _close_to_home = ((random() > 0.5) ? TRUE : FALSE);
entity _best = world, _trg_gen = world;
float _score, _best_score = MAX_SHOT_DISTANCE;
-
+
RandomSelection_Init();
-
+
if(self.team == NUM_TEAM_1)
{
if(!_close_to_home)
_trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
+ else
+ _trg_gen = ons_red_generator;
}
-
+
if(self.team == NUM_TEAM_2)
{
if(_close_to_home)
_trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
+ else
+ _trg_gen = ons_red_generator;
}
-
+
entity _cp = findchain(classname, "onslaught_controlpoint");
while(_cp)
{
- if(_cp.team == self.team)
- {
+ if(_cp.team == self.team)
+ {
_score = vlen(_trg_gen.origin - _cp.origin);
if(_score < _best_score)
{
_best = _cp;
- _best_score = _score;
+ _best_score = _score;
}
- }
+ }
_cp = _cp.chain;
}
-
- vector _loc;
- float i;
+
+ vector _loc;
+ float i;
if(_best)
{
for(i = 0; i < 10; ++i)
{
_loc = _best.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
+ _loc += ('0 1 0' * random()) * 128;
tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
if(trace_fraction == 1.0 && !trace_startsolid)
{
{
if(!autocvar_g_onslaught_spawn_at_generator)
return 0;
-
+
_trg_gen = ((self.team == NUM_TEAM_1) ? ons_red_generator : ons_blue_generator);
-
+
for(i = 0; i < 10; ++i)
{
_loc = _trg_gen.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
+ _loc += ('0 1 0' * random()) * 128;
tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
if(trace_fraction == 1.0 && !trace_startsolid)
{
}
}
}
-
+
return 0;
}
+MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
+{
+ entity e, ee = world;
+ if(self.targetname)
+ {
+ e = find(world, target, self.targetname);
++
+ if(e != world)
+ {
+ self.team = e.team;
+ ee = e;
+ }
+ }
+
+ if(ee)
+ {
+ activator = ee;
+ self.use();
+ }
++
++ return FALSE;
++}
++
+ MUTATOR_HOOKFUNCTION(ons_MonsterThink)
+ {
+ entity e = find(world, targetname, self.target);
+ if (e != world)
+ self.team = e.team;
+
+ return FALSE;
+ }
+
+ MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
+ {
+ entity e, ee = world;
- if(e != world)
- {
- self.team = e.team;
- ee = e;
- }
- }
-
- if(ee)
- {
+ if(self.targetname)
+ {
+ e = find(world,target,self.targetname);
+ activator = ee;
+ self.use();
+ }
+
return FALSE;
}
MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(TurretSpawn, ons_TurretSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(MonsterMove, ons_MonsterThink, CBC_ORDER_ANY);
+ MUTATOR_HOOK(MonsterSpawn, ons_MonsterSpawn, CBC_ORDER_ANY);
//MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
MUTATOR_ONADD
../common/command/shared_defs.qh
../common/net_notice.qh
../common/animdecide.qh
+ ../common/monsters/monsters.qh
+ ../common/monsters/sv_monsters.qh
+ ../common/monsters/spawn.qh
autocvars.qh
constants.qh
../common/notifications.qh // must be after autocvars
../common/deathtypes.qh // must be after notifications
+../common/turrets/config.qh
+../common/turrets/turrets.qh
+../common/turrets/sv_turrets.qh
+../common/turrets/util.qc
+
mutators/base.qh
mutators/mutators.qh
mutators/gamemode_assault.qh
- mutators/gamemode_arena.qh
mutators/gamemode_ca.qh
mutators/gamemode_ctf.qh
mutators/gamemode_domination.qh
mutators/gamemode_keepaway.qh
mutators/gamemode_nexball.qh
mutators/gamemode_lms.qh
+ mutators/gamemode_invasion.qh
mutators/mutator_dodging.qh
mutators/mutator_nades.qh
-//// tZork Turrets ////
-tturrets/include/turrets_early.qh
+//// tZork Vehicles ////
vehicles/vehicles_def.qh
campaign.qh
race.qc
-//// tZork Turrets ////
-tturrets/include/turrets.qh
+//// tZork Vehicles ////
vehicles/vehicles.qh
scores.qc
../common/explosion_equation.qc
+../common/turrets/sv_turrets.qc
+../common/turrets/config.qc
+../common/turrets/turrets.qc
+../common/turrets/checkpoint.qc
+../common/turrets/targettrigger.qc
+
+ ../common/monsters/sv_monsters.qc
+ ../common/monsters/monsters.qc
+
+ ../common/monsters/spawn.qc
+
mutators/base.qc
mutators/gamemode_assault.qc
- mutators/gamemode_arena.qc
mutators/gamemode_ca.qc
mutators/gamemode_ctf.qc
mutators/gamemode_domination.qc
mutators/gamemode_nexball.qc
mutators/gamemode_onslaught.qc
mutators/gamemode_lms.qc
+ mutators/gamemode_invasion.qc
mutators/mutator_invincibleproj.qc
mutators/mutator_new_toys.qc
mutators/mutator_nix.qc
../common/test.qc
../common/util.qc
../common/notifications.qc
-
- ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
if(head != player) \
if(head.takedamage) \
if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
-
+
float check_tdeath(entity player, vector org, vector telefragmin, vector telefragmax)
{
{
TDEATHLOOP(org)
{
- if not(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team)
+ if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
if(IS_PLAYER(head))
if(head.health >= 1)
return 1;
{
if (IS_PLAYER(player) && player.health >= 1)
{
- if not(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team)
+ if (!(teamplay && autocvar_g_telefrags_teamplay && head.team == player.team))
{
if(IS_PLAYER(head))
if(head.health >= 1)
vector locout;
entity e;
float p;
-
+
// Find the output teleporter
if(teleporter.enemy)
{
e = teleporter.enemy;
}
else
- {
+ {
RandomSelection_Init();
for(e = world; (e = find(e, targetname, teleporter.target)); )
{
}
if(!e) { sprint(player, "Teleport destination vanished. Sorry... please complain to the mapper.\n"); }
-
+
makevectors(e.mangle);
if(e.speed)
if(vlen(player.velocity) > e.speed)
player.velocity = normalize(player.velocity) * max(0, e.speed);
-
+
if(autocvar_g_teleport_maxspeed)
if(vlen(player.velocity) > autocvar_g_teleport_maxspeed)
player.velocity = normalize(player.velocity) * max(0, autocvar_g_teleport_maxspeed);
if (self.active != ACTIVE_ACTIVE)
return;
-
- if not(other.teleportable)
+
+ if (!other.teleportable)
return;
-
+
if(other.vehicle)
if(!other.vehicle.teleportable)
return;
-
+
- if(other.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+ if(other.turret_flags & TUR_FLAG_ISTURRET)
return;
-
+
if(other.deadflag != DEAD_NO)
return;
if(IS_PLAYER(other))
RemoveGrapplingHook(other);
-
+
entity e;
e = Simple_TeleportPlayer(self, other);
activator = other;
s = self.target; self.target = string_null;
SUB_UseTargets();
- if not(self.target) self.target = s;
+ if (!self.target) self.target = s;
oldself = self;
self = e;
return world;
}
- entity teleport_first;
+ entity teleport_first;
.entity teleport_next;
void spawnfunc_trigger_teleport (void)
{
self.angles = '0 0 0';
EXACTTRIGGER_INIT;
-
- self.active = ACTIVE_ACTIVE;
-
+
+ self.active = ACTIVE_ACTIVE;
+
self.use = trigger_teleport_use;
// this must be called to spawn the teleport waypoints for bots
objerror ("Teleporter with no target");
return;
}
-
+
self.teleport_next = teleport_first;
teleport_first = self;
}
self = vehic;
-
-
+
+
vehic.solid = SOLID_NOT;
//setorigin(gunner, vehic.origin);
gunner.velocity = vehic.velocity;
-
+
float _in, _out;
vehic.angles_x *= -1;
makevectors(vehic.angles);
{
_in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
_out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
- setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
+ setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
}
-
+
crosshair_trace(gunner);
vector _ct = trace_endpos;
vector ad;
WriteAngle(MSG_ONE, self.vehicle.angles_y);
WriteAngle(MSG_ONE, 0);
}
-
+
CSQCVehicleSetup(self, HUD_NORMAL);
setsize(self, PL_MIN, PL_MAX);
if(self == self.vehicle.owner.gunner1)
{
- self.vehicle.owner.gunner1 = world;
+ self.vehicle.owner.gunner1 = world;
}
else if(self == self.vehicle.owner.gunner2)
{
- self.vehicle.owner.gunner2 = world;
+ self.vehicle.owner.gunner2 = world;
v_right *= -1;
- }
+ }
else
dprint("^1self != gunner1 or gunner2, this is a BIG PROBLEM, tell tZork this happend.\n");
-
+
vector spot = self.vehicle.owner.origin + + v_up * 128 + v_right * 300;
spot = vehicles_findgoodexit(spot);
//setorigin(self , spot);
_gun.vehicle_hudmodel.viewmodelforclient = other;
CSQCVehicleSetup(other, other.hud);
-
+
vh_player = other;
vh_vehicle = _gun;
MUTATOR_CALLHOOK(VehicleEnter);
float vehicles_valid_pilot()
{
- if not(IS_PLAYER(other))
+ if (!IS_PLAYER(other))
return FALSE;
if(other.deadflag != DEAD_NO)
if(other.vehicle != world)
return FALSE;
- if not(IS_REAL_CLIENT(other))
+ if (!IS_REAL_CLIENT(other))
if(!autocvar_g_vehicles_allow_bots)
return FALSE;
// Pitch
ftmp = 0;
- if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit)
+ if(pilot.movement_x > 0 && vang_x < autocvar_g_vehicle_bumblebee_pitchlimit)
ftmp = 4;
- else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit)
+ else if(pilot.movement_x < 0 && vang_x > -autocvar_g_vehicle_bumblebee_pitchlimit)
ftmp = -8;
newvel_x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel_x , autocvar_g_vehicle_bumblebee_pitchlimit);
vehic.velocity += newvel * frametime;
pilot.velocity = pilot.movement = vehic.velocity;
-
+
if(autocvar_g_vehicle_bumblebee_healgun_locktime)
- {
+ {
if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
vehic.tur_head.enemy = world;
}
}
else
- {
+ {
vehic.tur_head.enemy = trace_ent;
vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
}
}
-
+
if(vehic.tur_head.enemy)
{
- trace_endpos = real_origin(vehic.tur_head.enemy);
- UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
+ trace_endpos = real_origin(vehic.tur_head.enemy);
+ UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
}
}
-
+
vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed);
{
vehic.gun3.enemy.realowner = pilot;
vehic.gun3.enemy.effects &= ~EF_NODRAW;
-
+
vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
vehic.gun3.enemy.SendFlags |= BRG_START;
-
+
traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
-
+
if(trace_ent)
{
if(autocvar_g_vehicle_bumblebee_raygun)
trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
}
- else if(trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+ else if(trace_ent.turret_flags & TUR_FLAG_ISTURRET)
{
if(trace_ent.health <= trace_ent.tur_health && autocvar_g_vehicle_bumblebee_healgun_hps)
trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.tur_health);
}
}
}
-
+
vehic.gun3.enemy.hook_end = trace_endpos;
setorigin(vehic.gun3.enemy, trace_endpos);
vehic.gun3.enemy.SendFlags |= BRG_END;
-
+
vehic.wait = time + 1;
}
else
vehic.gun3.enemy = world;
}
*/
-
+
VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
if(vehic.vehicle_flags & VHF_HASSHIELD)
VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
-
+
vehic.angles_x *= -1;
makevectors(vehic.angles);
vehic.angles_x *= -1;
void bumb_think()
{
self.movetype = MOVETYPE_TOSS;
-
+
//self.velocity = self.velocity * 0.5;
self.angles_z *= 0.8;
self.angles_x *= 0.8;
-
+
self.nextthink = time + 0.05;
-
+
if(!self.owner)
{
- entity oldself = self;
+ entity oldself = self;
if(self.gunner1)
{
self = self.gunner1;
other = oldother;
return;
}
-
+
if(self.gunner2)
{
self = self.gunner2;
self.touch();
other = oldother;
return;
- }
+ }
}
-
+
}
void bumb_enter()
self.touch = vehicles_touch;
self.think = bumb_think;
self.nextthink = time;
-
+
if(!self.owner)
return;
-
+
fixedmakevectors(self.angles);
vector spot;
- if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
+ if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
spot = self.origin + v_up * 128 + v_forward * 200;
else
spot = self.origin + v_up * 128 - v_forward * 200;
-
+
spot = vehicles_findgoodexit(spot);
-
+
// Hide beam
if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
self.gun3.enemy.effects |= EF_NODRAW;
self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
self.owner.velocity_z += 10;
setorigin(self.owner, spot);
-
+
antilag_clear(self.owner);
self.owner = world;
}
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
pointparticles(particleeffectnum("explosion_large"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
-
+
if(self.owner.deadflag == DEAD_DYING)
self.owner.deadflag = DEAD_DEAD;
-
+
remove(self);
}
void bumb_die()
{
entity oldself = self;
-
+
// Hide beam
if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
self.gun3.enemy.effects |= EF_NODRAW;
-
+
if(self.gunner1)
{
self = self.gunner1;
_body.touch = bumb_blowup;
else
_body.touch = func_null;
-
+
_body.think = bumb_diethink;
_body.nextthink = time;
_body.wait = time + 2 + (random() * 8);
_body.owner = self;
_body.enemy = self.enemy;
-
+
pointparticles(particleeffectnum("explosion_medium"), findbetterlocation(self.origin, 16), '0 0 0', 1);
-
+
self.health = 0;
self.event_damage = func_null;
self.solid = SOLID_CORPSE;
void bumb_impact()
{
- if(autocvar_g_vehicle_bumblebee_bouncepain_x)
- vehilces_impact(autocvar_g_vehicle_bumblebee_bouncepain_x,
- autocvar_g_vehicle_bumblebee_bouncepain_y,
- autocvar_g_vehicle_bumblebee_bouncepain_z);
+ if(autocvar_g_vehicle_bumblebee_bouncepain_x)
+ vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
}
void bumb_spawn(float _f)
setorigin(self.gun2.vehicle_viewport, '-85 0 50');
self.scale = 1.5;
-
+
// Raygun beam
if(self.gun3.enemy == world)
- {
+ {
self.gun3.enemy = spawn();
Net_LinkEntity(self.gun3.enemy, TRUE, 0, bumble_raygun_send);
- self.gun3.enemy.SendFlags = BRG_SETUP;
- self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
+ self.gun3.enemy.SendFlags = BRG_SETUP;
+ self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
}
}
self.movetype = MOVETYPE_TOSS;
self.vehicle_impact = bumb_impact;
self.damageforcescale = 0.025;
-
+
setorigin(self, self.origin + '0 0 25');
}
if(autocvar_g_vehicle_bumblebee_health_regen)
self.vehicle_flags |= VHF_HEALTHREGEN;
- if not(vehicle_initialize(
+ if(!vehicle_initialize(
"Bumblebee", "models/vehicles/bumblebee_body.dpm",
"", "models/vehicles/spiderbot_cockpit.dpm", "", "", "tag_viewport",
HUD_BUMBLEBEE, BUMB_MIN, BUMB_MAX, FALSE,
_len = vlen(self.origin - self.move_origin);
_dir = normalize(self.move_origin - self.origin);
-
+
if(self.total_damages < time)
{
boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
self.cnt = ReadByte();
self.team = ReadByte();
self.cnt = ReadByte();
-
+
if(self.cnt)
self.colormod = '1 0 0';
else
self.colormod = '0 1 0';
self.traileffect = particleeffectnum("healray_muzzleflash");
- self.lip = particleeffectnum("healray_impact");
+ self.lip = particleeffectnum("healray_impact");
self.draw = bumble_raygun_draw;
}
-
-
+
+
if(sf & BRG_START)
{
self.origin_x = ReadCoord();
void vehicles_enter();
void vehicles_touch();
void vehicles_reset_colors();
- void vehicles_clearrturn();
+ void vehicles_clearreturn();
void vehicles_setreturn();
void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id)
{
- if not(IS_REAL_CLIENT(own))
+ if (!IS_REAL_CLIENT(own))
return;
entity axh;
**/
void CSQCVehicleSetup(entity own, float vehicle_id)
{
- if not(IS_REAL_CLIENT(own))
+ if (!IS_REAL_CLIENT(own))
return;
-
+
msg_entity = own;
WriteByte(MSG_ONE, SVC_TEMPENTITY);
WriteByte(MSG_ONE, TE_CSQC_VEHICLESETUP);
if(vehicle_id != 0)
- WriteByte(MSG_ONE, vehicle_id);
+ WriteByte(MSG_ONE, vehicle_id);
else
WriteByte(MSG_ONE, 1 + own.vehicle.vehicle_weapon2mode + HUD_VEHICLE_LAST);
}
if(trace_ent.deadflag != DEAD_NO)
trace_ent = world;
- if not (trace_ent.vehicle_flags & VHF_ISVEHICLE ||
- trace_ent.turret_flags & TUR_FLAG_ISTURRET ||
- if(!trace_ent.vehicle_flags & VHF_ISVEHICLE ||
- trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET ||
-- trace_ent.takedamage == DAMAGE_TARGETDRONE)
++ if(!((trace_ent.vehicle_flags & VHF_ISVEHICLE) || (trace_ent.turret_flags & TUR_FLAG_ISTURRET)))
trace_ent = world;
}
}
// End generic vehile projectile system
+ void vehicles_reset()
+ {
+ if(self.owner)
+ {
+ entity oldself = self;
+ self = self.owner;
+ vehicles_exit(VHEF_RELESE);
+ self = oldself;
+ }
+ self.alpha = -1;
+ self.movetype = MOVETYPE_NONE;
+ self.effects = EF_NODRAW;
+ self.colormod = '0 0 0';
+ self.avelocity = '0 0 0';
+ self.velocity = '0 0 0';
+ self.event_damage = func_null;
+ self.solid = SOLID_NOT;
+ self.deadflag = DEAD_NO;
+
+ self.touch = func_null;
+ self.nextthink = 0;
+ vehicles_setreturn();
+ }
+
/** vehicles_spawn
Exetuted for all vehicles on (re)spawn.
Sets defaults for newly spawned units.
self.owner = world;
self.touch = vehicles_touch;
self.event_damage = vehicles_damage;
+ self.reset = vehicles_reset;
self.iscreature = TRUE;
self.teleportable = FALSE; // no teleporting for vehicles, too buggy
self.damagedbycontents = TRUE;
setorigin(self, self.pos1 + '0 0 0');
// Show it
pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
-
+
if(self.vehicle_controller)
self.team = self.vehicle_controller.team;
-
+
vehicles_reset_colors();
self.vehicle_spawn(VHSF_NORMAL);
}
return FALSE;
}
- void vehilces_impact(float _minspeed, float _speedfac, float _maxpain)
+ void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
{
if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
return;
{
if(MUTATOR_CALLHOOK(VehicleTouch))
return;
-
+
// Vehicle currently in use
if(self.owner)
{
return;
}
- if not(IS_PLAYER(other))
+ if (!IS_PLAYER(other))
return;
if(other.deadflag != DEAD_NO)
void vehicles_enter()
{
// Remove this when bots know how to use vehicles
-
- if (IS_BOT_CLIENT(other))
+
+ if (IS_BOT_CLIENT(other))
if (autocvar_g_vehicles_allow_bots)
dprint("Bot enters vehicle\n"); // This is where we need to disconnect (some, all?) normal bot AI and hand over to vehicle's _aiframe()
else
self.team = self.owner.team;
self.flags -= FL_NOTARGET;
-
+ self.monster_attack = TRUE;
+
if (IS_REAL_CLIENT(other))
{
msg_entity = other;
WriteByte (MSG_ONE, SVC_SETVIEWPORT);
WriteEntity(MSG_ONE, self.vehicle_viewport);
-
+
WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
if(self.tur_head)
{
}
}
- vehicles_clearrturn();
+ vehicles_clearreturn();
CSQCVehicleSetup(self.owner, self.hud);
-
+
vh_player = other;
vh_vehicle = self;
MUTATOR_CALLHOOK(VehicleEnter);
entity _vehicle;
entity _player;
entity _oldself = self;
-
+
if(vehicles_exit_running)
{
dprint("^1vehicles_exit allready running! this is not good..\n");
return;
}
-
+
vehicles_exit_running = TRUE;
if(IS_CLIENT(self))
{
_vehicle = self.vehicle;
-
+
if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
{
_vehicle.vehicle_exit(eject);
self = _oldself;
vehicles_exit_running = FALSE;
- return;
+ return;
}
}
else
_vehicle = self;
-
+
_player = _vehicle.owner;
-
+
self = _vehicle;
if (_player)
WriteAngle(MSG_ONE, _vehicle.angles_y);
WriteAngle(MSG_ONE, 0);
}
-
+
setsize(_player, PL_MIN,PL_MAX);
_player.takedamage = DAMAGE_AIM;
CSQCVehicleSetup(_player, HUD_NORMAL);
}
_vehicle.flags |= FL_NOTARGET;
-
+
if(_vehicle.deadflag == DEAD_NO)
_vehicle.avelocity = '0 0 0';
-
+
_vehicle.tur_head.nodrawtoclient = world;
-
+
if(!teamplay)
_vehicle.team = 0;
_vehicle = vh_vehicle;
_vehicle.team = _vehicle.tur_head.team;
-
+
sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTEN_NORM);
- _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
+ _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
_vehicle.phase = time + 1;
-
+ _vehicle.monster_attack = FALSE;
+
_vehicle.vehicle_exit(eject);
-
+
vehicles_setreturn();
- vehicles_reset_colors();
+ vehicles_reset_colors();
_vehicle.owner = world;
self = _oldself;
-
+
vehicles_exit_running = FALSE;
}
{
if(_healthscale)
regen = regen * (self.vehicle_health / self.tur_health);
-
+
self.regen_field = min(self.regen_field + regen * delta_time, field_max);
if(self.owner)
void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
self.dmg_time = time;
-
+
if(DEATH_ISWEAPON(deathtype, WEP_NEX))
damage *= autocvar_g_vehicles_nex_damagerate;
-
+
if(DEATH_ISWEAPON(deathtype, WEP_UZI))
damage *= autocvar_g_vehicles_uzi_damagerate;
-
+
if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
damage *= autocvar_g_vehicles_rifle_damagerate;
-
+
if(DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
damage *= autocvar_g_vehicles_minstanex_damagerate;
if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
damage *= autocvar_g_vehicles_tag_damagerate;
-
+
self.enemy = attacker;
-
+
if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
{
if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world)
if(sound_allowed(MSG_BROADCAST, attacker))
spamsound (self, CH_PAIN, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM); // FIXME: PLACEHOLDER
}
-
+
if(self.damageforcescale < 1 && self.damageforcescale > 0)
self.velocity += force * self.damageforcescale;
else
}
}
- void vehicles_clearrturn()
+ void vehicles_clearreturn()
{
entity ret;
// Remove "return helper", if any.
{
entity ret;
- vehicles_clearrturn();
+ vehicles_clearreturn();
ret = spawn();
ret.classname = "vehicle_return";
ret.team = self.team;
ret.think = vehicles_showwp;
- if(self.deadflag != DEAD_NO)
- {
- ret.cnt = time + self.vehicle_respawntime;
- ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 5);
- }
- else
- {
- ret.nextthink = min(time + self.vehicle_respawntime, time + self.vehicle_respawntime - 1);
- }
+ if(self.deadflag != DEAD_NO)
+ {
+ ret.cnt = max(game_starttime, time) + self.vehicle_respawntime;
+ ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 5);
+ }
+ else
+ ret.nextthink = max(game_starttime, time) + max(0, self.vehicle_respawntime - 1);
setmodel(ret, "null");
setorigin(ret, self.pos1 + '0 0 96');
-
}
void vehicles_reset_colors()
self.active = ACTIVE_NOT;
else
self.active = ACTIVE_ACTIVE;
-
+
if(self.active == ACTIVE_ACTIVE && self.deadflag == DEAD_NO)
{
dprint("^3Eat shit yall!\n");
}
else if(self.active == ACTIVE_NOT && self.deadflag != DEAD_NO)
{
-
+
}
}
- float vehicle_addplayerslot( entity _owner,
- entity _slot,
- float _hud,
+ float vehicle_addplayerslot( entity _owner,
+ entity _slot,
+ float _hud,
string _hud_model,
- float() _framefunc,
+ float() _framefunc,
void(float) _exitfunc)
{
- if not (_owner.vehicle_flags & VHF_MULTISLOT)
+ if (!(_owner.vehicle_flags & VHF_MULTISLOT))
_owner.vehicle_flags |= VHF_MULTISLOT;
_slot.PlayerPhysplug = _framefunc;
_slot.vehicle_hudmodel = spawn();
_slot.vehicle_hudmodel.viewmodelforclient = _slot;
_slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
-
+
setmodel(_slot.vehicle_hudmodel, _hud_model);
setmodel(_slot.vehicle_viewport, "null");
-
+
setattachment(_slot.vehicle_hudmodel, _slot, "");
setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
-
+
return TRUE;
}
{
if(!autocvar_g_vehicles)
return FALSE;
-
+
if(self.targetname)
{
self.vehicle_controller = find(world, target, self.targetname);
}
else
{
- self.team = self.vehicle_controller.team;
+ self.team = self.vehicle_controller.team;
self.use = vehicle_use;
-
+
if(teamplay)
{
if(self.vehicle_controller.team == 0)
self.active = ACTIVE_NOT;
else
- self.active = ACTIVE_ACTIVE;
+ self.active = ACTIVE_ACTIVE;
}
}
}
-
+
precache_sound("onslaught/ons_hit2.wav");
precache_sound("onslaught/electricity_explode.wav");
self.event_damage = func_null;
self.touch = vehicles_touch;
self.think = vehicles_spawn;
- self.nextthink = time;
- self.vehicle_respawntime = _respawntime;
self.vehicle_spawn = spawnproc;
+ self.vehicle_respawntime = max(0, _respawntime);
self.effects = EF_NODRAW;
self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
- if(!autocvar_g_vehicles_delayspawn)
- self.nextthink = time + game_starttime;
- else
- self.nextthink = time + _respawntime + (random() * autocvar_g_vehicles_delayspawn_jitter);
+ if(!autocvar_g_vehicles_delayspawn || !self.vehicle_respawntime)
+ self.nextthink = time;
+ else
+ self.nextthink = max(time, game_starttime) + max(0, self.vehicle_respawntime + ((random() * 2 - 1) * autocvar_g_vehicles_delayspawn_jitter));
if(autocvar_g_playerclip_collisions)
self.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
}
setsize(self, min_s, max_s);
- if not (nodrop)
+ if (!nodrop)
{
setorigin(self, self.origin);
tracebox(self.origin + '0 0 100', min_s, max_s, self.origin - '0 0 10000', MOVE_WORLDONLY, self);
setorigin(self, trace_endpos);
}
-
+
self.pos1 = self.origin;
self.pos2 = self.angles;
self.tur_head.team = self.team;
-
+
if(MUTATOR_CALLHOOK(VehicleSpawn))
return FALSE;
return TRUE;
}
- vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
- float _pichlimit_min, float _pichlimit_max,
+ vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string _tagname,
+ float _pichlimit_min, float _pichlimit_max,
float _rotlimit_min, float _rotlimit_max, float _aimspeed)
{
vector vtmp, vtag;
ftmp = _aimspeed * frametime;
vtmp_y = bound(-ftmp, vtmp_y, ftmp);
vtmp_x = bound(-ftmp, vtmp_x, ftmp);
- _turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max);
+ _turrret.angles_y = bound(_rotlimit_min, _turrret.angles_y + vtmp_y, _rotlimit_max);
_turrret.angles_x = bound(_pichlimit_min, _turrret.angles_x + vtmp_x, _pichlimit_max);
return vtag;
}
_gib.movetype = MOVETYPE_TOSS;
_gib.solid = SOLID_CORPSE;
_gib.colormod = '-0.5 -0.5 -0.5';
- _gib.effects = EF_LOWPRECISION;
+ _gib.effects = EF_LOWPRECISION;
_gib.avelocity = _rot;
-
+
if(_burn)
_gib.effects |= EF_FLAME;
-
+
if(_explode)
{
- _gib.think = vehicles_gib_explode;
+ _gib.think = vehicles_gib_explode;
_gib.nextthink = time + random() * _explode;
_gib.touch = vehicles_gib_explode;
}
else
{
_gib.cnt = time + _maxtime;
- _gib.think = vehicles_gib_think;
- _gib.nextthink = time + _maxtime - 1;
+ _gib.think = vehicles_gib_think;
+ _gib.nextthink = time + _maxtime - 1;
_gib.alpha = 1;
}
return _gib;
.float vehicle_respawntime;
//.void() vehicle_spawn;
+.float volly_counter;
+
+.float tur_health;
+
void vehicles_exit(float eject);
.void(float exit_flags) vehicle_exit;
const float VHEF_NORMAL = 0; /// User pressed exit key
#define VHSF_NORMAL 0
#define VHSF_FACTORY 2
.void(float _spawnflag) vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
- .float(float _imp) vehicles_impusle;
+ .float(float _imp) vehicles_impulse;
.float vehicle_weapon2mode = volly_counter;
- //ยง .void() vehicle_factory()
-
#ifdef VEHICLES_USE_ODE
void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
void(entity e, vector force, vector force_pos) physics_addforce = #541; // apply a force from certain origin, length of force vector is power of force