[nexuiz-commits] r7131 - in trunk/data/qcsrc: client common menu/nexuiz server server/monsters server/pathlib server/tturrets/include server/tturrets/system server/tturrets/units server/vehicles
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Tue Jun 30 10:36:37 EDT 2009
Author: div0
Date: 2009-06-30 10:36:36 -0400 (Tue, 30 Jun 2009)
New Revision: 7131
Modified:
trunk/data/qcsrc/client/Defs.qc
trunk/data/qcsrc/client/Main.qc
trunk/data/qcsrc/client/View.qc
trunk/data/qcsrc/client/bgmscript.qc
trunk/data/qcsrc/client/bgmscript.qh
trunk/data/qcsrc/client/casings.qc
trunk/data/qcsrc/client/csqc_builtins.qc
trunk/data/qcsrc/client/csqc_constants.qc
trunk/data/qcsrc/client/ctf.qc
trunk/data/qcsrc/client/damage.qc
trunk/data/qcsrc/client/effects.qc
trunk/data/qcsrc/client/gibs.qc
trunk/data/qcsrc/client/hook.qc
trunk/data/qcsrc/client/interpolate.qc
trunk/data/qcsrc/client/interpolate.qh
trunk/data/qcsrc/client/laser.qc
trunk/data/qcsrc/client/main.qh
trunk/data/qcsrc/client/mapvoting.qc
trunk/data/qcsrc/client/movetypes.qc
trunk/data/qcsrc/client/movetypes.qh
trunk/data/qcsrc/client/particles.qc
trunk/data/qcsrc/client/prandom.qc
trunk/data/qcsrc/client/prandom.qh
trunk/data/qcsrc/client/pre.qh
trunk/data/qcsrc/client/projectile.qc
trunk/data/qcsrc/client/rubble.qc
trunk/data/qcsrc/client/sortlist.qc
trunk/data/qcsrc/client/teamplay.qc
trunk/data/qcsrc/client/teamradar.qc
trunk/data/qcsrc/client/teamradar.qh
trunk/data/qcsrc/client/wall.qc
trunk/data/qcsrc/client/waypointsprites.qc
trunk/data/qcsrc/client/waypointsprites.qh
trunk/data/qcsrc/common/items.qc
trunk/data/qcsrc/common/items.qh
trunk/data/qcsrc/common/util-pre.qh
trunk/data/qcsrc/menu/nexuiz/bigbutton.c
trunk/data/qcsrc/menu/nexuiz/bigcommandbutton.c
trunk/data/qcsrc/menu/nexuiz/colorpicker.c
trunk/data/qcsrc/menu/nexuiz/cvarlist.c
trunk/data/qcsrc/menu/nexuiz/demolist.c
trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_advanced.c
trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_demo.c
trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_join_serverinfo.c
trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup_radar.c
trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup_weapons.c
trunk/data/qcsrc/menu/nexuiz/dialog_settings_audio.c
trunk/data/qcsrc/menu/nexuiz/dialog_settings_misc_cvars.c
trunk/data/qcsrc/menu/nexuiz/dialog_settings_network.c
trunk/data/qcsrc/menu/nexuiz/modbutton.c
trunk/data/qcsrc/menu/nexuiz/playerlist.c
trunk/data/qcsrc/menu/nexuiz/skinlist.c
trunk/data/qcsrc/menu/nexuiz/weaponslist.c
trunk/data/qcsrc/server/bots_scripting.qc
trunk/data/qcsrc/server/csqceffects.qc
trunk/data/qcsrc/server/csqcprojectile.qc
trunk/data/qcsrc/server/csqcprojectile.qh
trunk/data/qcsrc/server/ent_cs.qc
trunk/data/qcsrc/server/func_breakable.qc
trunk/data/qcsrc/server/g_hook.qh
trunk/data/qcsrc/server/g_models.qc
trunk/data/qcsrc/server/havocbot_ons.qc
trunk/data/qcsrc/server/monsters/ai.qc
trunk/data/qcsrc/server/monsters/defs.qc
trunk/data/qcsrc/server/monsters/fight.qc
trunk/data/qcsrc/server/monsters/m_monsters.qc
trunk/data/qcsrc/server/monsters/mode_management.qc
trunk/data/qcsrc/server/movelib.qc
trunk/data/qcsrc/server/nexball.qc
trunk/data/qcsrc/server/pathlib.qc
trunk/data/qcsrc/server/pathlib/costs.qc
trunk/data/qcsrc/server/pathlib/debug.qc
trunk/data/qcsrc/server/pathlib/expandnode.qc
trunk/data/qcsrc/server/pathlib/main.qc
trunk/data/qcsrc/server/pathlib/movenode.qc
trunk/data/qcsrc/server/pathlib/pathlib.qh
trunk/data/qcsrc/server/pathlib/utility.qc
trunk/data/qcsrc/server/portals.qc
trunk/data/qcsrc/server/portals.qh
trunk/data/qcsrc/server/post-builtins.qh
trunk/data/qcsrc/server/pre-builtins.qh
trunk/data/qcsrc/server/race.qc
trunk/data/qcsrc/server/race.qh
trunk/data/qcsrc/server/scores.qc
trunk/data/qcsrc/server/scores.qh
trunk/data/qcsrc/server/scores_rules.qc
trunk/data/qcsrc/server/steerlib.qc
trunk/data/qcsrc/server/target_spawn.qc
trunk/data/qcsrc/server/tturrets/include/turrets.qh
trunk/data/qcsrc/server/tturrets/include/turrets_early.qh
trunk/data/qcsrc/server/tturrets/system/system_aimprocs.qc
trunk/data/qcsrc/server/tturrets/system/system_main.qc
trunk/data/qcsrc/server/tturrets/system/system_misc.qc
trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc
trunk/data/qcsrc/server/tturrets/units/unit_checkpoint.qc
trunk/data/qcsrc/server/tturrets/units/unit_common.qc
trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc
trunk/data/qcsrc/server/tturrets/units/unit_flac.qc
trunk/data/qcsrc/server/tturrets/units/unit_fusionreactor.qc
trunk/data/qcsrc/server/tturrets/units/unit_hellion.qc
trunk/data/qcsrc/server/tturrets/units/unit_hk.qc
trunk/data/qcsrc/server/tturrets/units/unit_machinegun.qc
trunk/data/qcsrc/server/tturrets/units/unit_mlrs.qc
trunk/data/qcsrc/server/tturrets/units/unit_phaser.qc
trunk/data/qcsrc/server/tturrets/units/unit_plasma.qc
trunk/data/qcsrc/server/tturrets/units/unit_targettrigger.qc
trunk/data/qcsrc/server/tturrets/units/unit_tessla.qc
trunk/data/qcsrc/server/tturrets/units/unit_walker.qc
trunk/data/qcsrc/server/vehicles/vehicles.qh
trunk/data/qcsrc/server/verbstack.qc
trunk/data/qcsrc/server/vote.qc
trunk/data/qcsrc/server/vote.qh
trunk/data/qcsrc/server/w_campingrifle.qc
trunk/data/qcsrc/server/w_hlac.qc
trunk/data/qcsrc/server/w_hook.qc
trunk/data/qcsrc/server/w_minstanex.qc
trunk/data/qcsrc/server/w_porto.qc
trunk/data/qcsrc/server/w_seeker.qc
trunk/data/qcsrc/server/w_tuba.qc
Log:
eol-style only
Modified: trunk/data/qcsrc/client/Defs.qc
===================================================================
--- trunk/data/qcsrc/client/Defs.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/Defs.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,235 +1,235 @@
-#pragma flag off fastarrays // make dp behave with new fteqcc versions. remove when dp bug with fteqcc fastarrays is fixed
-
-
-//NOTE: THIS IS AN INTERFACE FILE. DO NOT EDIT.
-//MODIFYING THIS FILE CAN RESULT IN CRC ERRORS.
-//YOU HAVE BEEN WARNED.
-
-//feel free to look though. :)
-
-
-
-
-
-/*
-==============================================================================
-
- SOURCE FOR GLOBALVARS_T C STRUCTURE
-
-==============================================================================
-*/
-
-//
-// system globals
-//
-entity self;
-entity other;
-entity world;
-float time;
-float frametime;
-
-float player_localentnum; //the entnum
-float player_localnum; //the playernum
-float maxclients; //a constant filled in by the engine. gah, portability eh?
-
-float clientcommandframe; //player movement
-float servercommandframe; //clientframe echoed off the server
-
-string mapname;
-
-//
-// global variables set by built in functions
-//
-vector v_forward, v_up, v_right; // set by makevectors()
-
-// set by traceline / tracebox
-float trace_allsolid;
-float trace_startsolid;
-float trace_fraction;
-vector trace_endpos;
-vector trace_plane_normal;
-float trace_plane_dist;
-entity trace_ent;
-float trace_inopen;
-float trace_inwater;
-
-//
-// required prog functions
-//
-void() CSQC_Init;
-void() CSQC_Shutdown;
-float(float f, float t, float n) CSQC_InputEvent;
-void(float w, float h) CSQC_UpdateView;
-float(string s) CSQC_ConsoleCommand;
-
-//these fields are read and set by the default player physics
-vector pmove_org;
-vector pmove_vel;
-vector pmove_mins;
-vector pmove_maxs;
-//retrieved from the current movement commands (read by player physics)
-float input_timelength;
-vector input_angles;
-vector input_movevalues; //forwards, right, up.
-float input_buttons; //attack, use, jump (default physics only uses jump)
-
-float movevar_gravity;
-float movevar_stopspeed;
-float movevar_maxspeed;
-float movevar_spectatormaxspeed; //used by NOCLIP movetypes.
-float movevar_accelerate;
-float movevar_airaccelerate;
-float movevar_wateraccelerate;
-float movevar_friction;
-float movevar_waterfriction;
-float movevar_entgravity; //the local player's gravity field. Is a multiple (1 is the normal value)
-
-//================================================
-void end_sys_globals; // flag for structure dumping
-//================================================
-
-/*
-==============================================================================
-
- SOURCE FOR ENTVARS_T C STRUCTURE
-
-==============================================================================
-*/
-
-//
-// system fields (*** = do not set in prog code, maintained by C code)
-//
-.float modelindex; // *** model index in the precached list
-.vector absmin, absmax; // *** origin + mins / maxs
-
-.float entnum; // *** the ent number as on the server
-.float drawmask;
-.void() predraw;
-
-.float movetype;
-.float solid;
-
-.vector origin; // ***
-.vector oldorigin; // ***
-.vector velocity;
-.vector angles;
-.vector avelocity;
-
-.string classname; // spawn function
-.string model;
-.float frame;
-.float skin;
-.float effects;
-
-.vector mins, maxs; // bounding box extents reletive to origin
-.vector size; // maxs - mins
-
-.void() touch;
-.void() use;
-.void() think;
-.void() blocked; // for doors or plats, called when can't push other
-
-.float nextthink;
-
-.entity chain;
-
-.string netname;
-
-.entity enemy;
-
-.float flags;
-
-.float colormap;
-
-.entity owner; // who launched a missile
-
-//================================================
-void end_sys_fields; // flag for structure dumping
-//================================================
-
-// Additional OPTIONAL Fields and Globals
-float intermission;
-float sb_showscores;
-float sb_showaccuracy;
-float sbar_currentammo;
-.string message;
-.float renderflags;
-// float coop;
-// float deathmatch;
-
-// float dmg_take;
-// float dmg_save;
-// vector dmg_origin;
-
-// Darkplaces Render Modifications
-#if 0
-.float alpha;
-.float renderflags;
-.vector colormod;
-.float scale;
-#endif
-
-// Basic variables
-.float enttype; // entity type sent from server
-.float sv_entnum; // entity number sent from server
-.float team;
-.float team_size;
-
-float vid_conwidth, vid_conheight;
-float binddb;
-
-// QUALIFYING
-float race_checkpoint;
-float race_time;
-float race_laptime;
-float race_checkpointtime;
-float race_previousbesttime;
-string race_previousbestname;
-float race_nextcheckpoint;
-float race_nextbesttime;
-string race_nextbestname;
-
-// RACE
-float race_mycheckpoint;
-float race_mycheckpointtime;
-float race_mycheckpointdelta;
-float race_mycheckpointlapsdelta;
-string race_mycheckpointenemy;
-float race_othercheckpoint;
-float race_othercheckpointtime;
-float race_othercheckpointdelta;
-float race_othercheckpointlapsdelta;
-string race_othercheckpointenemy;
-float sb_showscores_force;
-
-// Nexball
-float nb_pb_period;
-
-// Spectating
-float spectatee_status;
-
-// short mapname
-string shortmapname;
-
-//remaining maptime announcer sounds, true when sound was already played
-float announcer_1min;
-float announcer_5min;
-
-// database for misc stuff
-float tempdb;
-vector hook_shotorigin;
-
-#ifdef BLURTEST
-float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
-#endif
-
-float servertime, serverprevtime, serverdeltatime;
-
-float ticrate;
-
-.float damageforcescale;
-.void(float thisdmg, float hittype, vector org, vector thisforce) event_damage;
-
-// only for Porto
-float angles_held_status;
-vector angles_held;
+#pragma flag off fastarrays // make dp behave with new fteqcc versions. remove when dp bug with fteqcc fastarrays is fixed
+
+
+//NOTE: THIS IS AN INTERFACE FILE. DO NOT EDIT.
+//MODIFYING THIS FILE CAN RESULT IN CRC ERRORS.
+//YOU HAVE BEEN WARNED.
+
+//feel free to look though. :)
+
+
+
+
+
+/*
+==============================================================================
+
+ SOURCE FOR GLOBALVARS_T C STRUCTURE
+
+==============================================================================
+*/
+
+//
+// system globals
+//
+entity self;
+entity other;
+entity world;
+float time;
+float frametime;
+
+float player_localentnum; //the entnum
+float player_localnum; //the playernum
+float maxclients; //a constant filled in by the engine. gah, portability eh?
+
+float clientcommandframe; //player movement
+float servercommandframe; //clientframe echoed off the server
+
+string mapname;
+
+//
+// global variables set by built in functions
+//
+vector v_forward, v_up, v_right; // set by makevectors()
+
+// set by traceline / tracebox
+float trace_allsolid;
+float trace_startsolid;
+float trace_fraction;
+vector trace_endpos;
+vector trace_plane_normal;
+float trace_plane_dist;
+entity trace_ent;
+float trace_inopen;
+float trace_inwater;
+
+//
+// required prog functions
+//
+void() CSQC_Init;
+void() CSQC_Shutdown;
+float(float f, float t, float n) CSQC_InputEvent;
+void(float w, float h) CSQC_UpdateView;
+float(string s) CSQC_ConsoleCommand;
+
+//these fields are read and set by the default player physics
+vector pmove_org;
+vector pmove_vel;
+vector pmove_mins;
+vector pmove_maxs;
+//retrieved from the current movement commands (read by player physics)
+float input_timelength;
+vector input_angles;
+vector input_movevalues; //forwards, right, up.
+float input_buttons; //attack, use, jump (default physics only uses jump)
+
+float movevar_gravity;
+float movevar_stopspeed;
+float movevar_maxspeed;
+float movevar_spectatormaxspeed; //used by NOCLIP movetypes.
+float movevar_accelerate;
+float movevar_airaccelerate;
+float movevar_wateraccelerate;
+float movevar_friction;
+float movevar_waterfriction;
+float movevar_entgravity; //the local player's gravity field. Is a multiple (1 is the normal value)
+
+//================================================
+void end_sys_globals; // flag for structure dumping
+//================================================
+
+/*
+==============================================================================
+
+ SOURCE FOR ENTVARS_T C STRUCTURE
+
+==============================================================================
+*/
+
+//
+// system fields (*** = do not set in prog code, maintained by C code)
+//
+.float modelindex; // *** model index in the precached list
+.vector absmin, absmax; // *** origin + mins / maxs
+
+.float entnum; // *** the ent number as on the server
+.float drawmask;
+.void() predraw;
+
+.float movetype;
+.float solid;
+
+.vector origin; // ***
+.vector oldorigin; // ***
+.vector velocity;
+.vector angles;
+.vector avelocity;
+
+.string classname; // spawn function
+.string model;
+.float frame;
+.float skin;
+.float effects;
+
+.vector mins, maxs; // bounding box extents reletive to origin
+.vector size; // maxs - mins
+
+.void() touch;
+.void() use;
+.void() think;
+.void() blocked; // for doors or plats, called when can't push other
+
+.float nextthink;
+
+.entity chain;
+
+.string netname;
+
+.entity enemy;
+
+.float flags;
+
+.float colormap;
+
+.entity owner; // who launched a missile
+
+//================================================
+void end_sys_fields; // flag for structure dumping
+//================================================
+
+// Additional OPTIONAL Fields and Globals
+float intermission;
+float sb_showscores;
+float sb_showaccuracy;
+float sbar_currentammo;
+.string message;
+.float renderflags;
+// float coop;
+// float deathmatch;
+
+// float dmg_take;
+// float dmg_save;
+// vector dmg_origin;
+
+// Darkplaces Render Modifications
+#if 0
+.float alpha;
+.float renderflags;
+.vector colormod;
+.float scale;
+#endif
+
+// Basic variables
+.float enttype; // entity type sent from server
+.float sv_entnum; // entity number sent from server
+.float team;
+.float team_size;
+
+float vid_conwidth, vid_conheight;
+float binddb;
+
+// QUALIFYING
+float race_checkpoint;
+float race_time;
+float race_laptime;
+float race_checkpointtime;
+float race_previousbesttime;
+string race_previousbestname;
+float race_nextcheckpoint;
+float race_nextbesttime;
+string race_nextbestname;
+
+// RACE
+float race_mycheckpoint;
+float race_mycheckpointtime;
+float race_mycheckpointdelta;
+float race_mycheckpointlapsdelta;
+string race_mycheckpointenemy;
+float race_othercheckpoint;
+float race_othercheckpointtime;
+float race_othercheckpointdelta;
+float race_othercheckpointlapsdelta;
+string race_othercheckpointenemy;
+float sb_showscores_force;
+
+// Nexball
+float nb_pb_period;
+
+// Spectating
+float spectatee_status;
+
+// short mapname
+string shortmapname;
+
+//remaining maptime announcer sounds, true when sound was already played
+float announcer_1min;
+float announcer_5min;
+
+// database for misc stuff
+float tempdb;
+vector hook_shotorigin;
+
+#ifdef BLURTEST
+float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
+#endif
+
+float servertime, serverprevtime, serverdeltatime;
+
+float ticrate;
+
+.float damageforcescale;
+.void(float thisdmg, float hittype, vector org, vector thisforce) event_damage;
+
+// only for Porto
+float angles_held_status;
+vector angles_held;
Property changes on: trunk/data/qcsrc/client/Defs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/Main.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,1067 +1,1067 @@
-// --------------------------------------------------------------------------
-// BEGIN REQUIRED CSQC FUNCTIONS
-//include "main.qh"
-
-#define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
-
-void cvar_clientsettemp(string cv, string val)
-{
- entity e;
- for(e = world; (e = find(e, classname, "saved_cvar_value")); )
- if(e.netname == cv)
- goto saved;
- e = spawn();
- e.classname = "saved_cvar_value";
- e.netname = strzone(cv);
- e.message = strzone(cvar_string(cv));
-:saved
- cvar_set(cv, val);
-}
-
-void cvar_clientsettemp_restore()
-{
- entity e;
- for(e = world; (e = find(e, classname, "saved_cvar_value")); )
- cvar_set(e.netname, e.message);
-}
-
-void() menu_show_error =
-{
- drawstring('0 200 0', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0);
-};
-
-// CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
-// Useful for precaching things
-
-void() menu_sub_null =
-{
-};
-
-#ifdef USE_FTE
-float __engine_check;
-#endif
-
-string forcefog;
-void WaypointSprite_Load();
-void CSQC_Init(void)
-{
-#ifdef USE_FTE
-#pragma target ID
- __engine_check = checkextension("DP_SV_WRITEPICTURE");
- if(!__engine_check)
- {
- print("^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n");
- localcmd("\ndisconnect\n");
- return;
- }
-#pragma target FTE
-#endif
-
- check_unacceptable_compiler_bugs();
-
- float i;
- CSQC_CheckEngine();
- dprint_load();
-
- binddb = db_create();
- tempdb = db_create();
- compressShortVector_init();
-
- drawfont = 0;
- menu_visible = FALSE;
- menu_show = menu_show_error;
- menu_action = menu_sub_null;
-
- for(i = 0; i < 255; ++i)
- if(getplayerkey(i, "viewentity") == "")
- break;
- maxclients = i;
-
- //ctf_temp_1 = "";
- // localcmd("alias order \"cmd order $*\""); enable if ctf-command thingy is used
- //registercmd("ctf_menu");
- registercmd("ons_map");
- //registercmd("menu_action");
-
- registercmd("+button3");
- registercmd("-button3");
- registercmd("+button4");
- registercmd("-button4");
- registercmd("+showaccuracy");registercmd("-showaccuracy");
-
-#ifndef CAMERATEST
- if(isdemo())
- {
-#endif
- registercmd("+forward");registercmd("-forward");
- registercmd("+back");registercmd("-back");
- registercmd("+moveup");registercmd("-moveup");
- registercmd("+movedown");registercmd("-movedown");
- registercmd("+moveright");registercmd("-moveright");
- registercmd("+moveleft");registercmd("-moveleft");
- registercmd("+roll_right");registercmd("-roll_right");
- registercmd("+roll_left");registercmd("-roll_left");
-#ifndef CAMERATEST
- }
-#endif
- registercvar("sbar_usecsqc", "1");
- registercvar("sbar_columns", "default", CVAR_SAVE);
-
- gametype = 0;
-
- // sbar_fields uses strunzone on the titles!
- for(i = 0; i < MAX_SBAR_FIELDS; ++i)
- sbar_title[i] = strzone("(null)");
-
- postinit = false;
-
- teams = Sort_Spawn();
- players = Sort_Spawn();
-
- GetTeam(COLOR_SPECTATOR, true); // add specs first
-
- cvar_clientsettemp("_supports_weaponpriority", "1");
-
-
-
-
- cs_project_is_b0rked = TRUE;
- R_SetView(VF_VIEWPORT, '0 0 0', '640 480 0');
- R_SetView(VF_FOV, '90 90 0');
- R_SetView(VF_ORIGIN, '0 0 0');
- R_SetView(VF_ANGLES, '0 0 0');
- R_SetView(VF_PERSPECTIVE, 1);
- makevectors('0 0 0');
- vector v;
- v = cs_project(v_forward);
- if(v_x - 320 < +1)
- if(v_x - 320 > -1)
- if(v_y - 240 < +1)
- if(v_y - 240 > -1)
- cs_project_is_b0rked = FALSE;
-
- RegisterWeapons();
-
- WaypointSprite_Load();
-
- Projectile_Precache();
- GibSplash_Precache();
- Casings_Precache();
- DamageInfo_Precache();
- Announcer_Precache();
-
- get_mi_min_max_texcoords(1); // try the CLEVER way first
- minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
- shortmapname = mi_shortname;
-
- if(precache_pic(minimapname) == "")
- {
- // but maybe we have a non-clever minimap
- minimapname = strcat("gfx/", mi_shortname, "_mini.tga");
- if(precache_pic(minimapname) == "")
- minimapname = ""; // FAIL
- else
- get_mi_min_max_texcoords(0); // load new texcoords
- }
-
- mi_center = (mi_min + mi_max) * 0.5;
- mi_scale = mi_max - mi_min;
- minimapname = strzone(minimapname);
-}
-
-// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
-void CSQC_Shutdown(void)
-{
-#ifdef USE_FTE
-#pragma TARGET id
- if(!__engine_check)
- return 0;
-#pragma TARGET fte
-#endif
-
- remove(teams);
- remove(players);
- db_close(binddb);
- db_close(tempdb);
-
- cvar_clientsettemp_restore();
-
- if(camera_active)
- cvar_set("chase_active",ftos(chase_active_backup));
-}
-
-.float has_team;
-float SetTeam(entity o, float Team)
-{
- entity tm;
- if(Team == -1) // leave
- {
- if(o.has_team)
- {
- //print("(DISCONNECT) leave team ", ftos(o.team), "\n");
- tm = GetTeam(o.team, false);
- tm.team_size -= 1;
- o.has_team = 0;
- return TRUE;
- }
- }
- else
- {
- if not(o.has_team)
- {
- //print("(CONNECT) enter team ", ftos(o.team), "\n");
- o.team = Team;
- tm = GetTeam(Team, true);
- tm.team_size += 1;
- o.has_team = 1;
- return TRUE;
- }
- else if(Team != o.team)
- {
- //print("(CHANGE) leave team ", ftos(o.team), "\n");
- tm = GetTeam(o.team, false);
- tm.team_size -= 1;
- o.team = Team;
- //print("(CHANGE) enter team ", ftos(o.team), "\n");
- tm = GetTeam(Team, true);
- tm.team_size += 1;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-void Playerchecker_Think()
-{
- float i;
- entity e;
- for(i = 0; i < maxclients; ++i)
- {
- e = playerslots[i];
- if(GetPlayerName(i) == "")
- {
- if(e.sort_prev)
- {
- //print("playerchecker: KILL KILL KILL\n");
- // player disconnected
- SetTeam(e, -1);
- RemovePlayer(e);
- e.sort_prev = world;
- //e.gotscores = 0;
- }
- }
- else
- {
- if not(e.sort_prev)
- {
- //print("playerchecker: SPAWN SPAWN SPAWN\n");
- // player connected
- if not(e)
- playerslots[i] = e = spawn();
- e.sv_entnum = i;
- //e.gotscores = 0; // we might already have the scores...
- SetTeam(e, GetPlayerColor(i)); // will not hurt; later updates come with Sbar_UpdatePlayerTeams
- RegisterPlayer(e);
- Sbar_UpdatePlayerPos(e);
- }
- }
- }
- self.nextthink = time + 0.2;
-}
-
-void Porto_Init();
-void TrueAim_Init();
-void PostInit(void)
-{
- print(strcat("PostInit\n maxclients = ", ftos(maxclients), "\n"));
- localcmd(strcat("\nsbar_columns_set ", cvar_string("sbar_columns"), ";\n"));
-
- entity playerchecker;
- playerchecker = spawn();
- playerchecker.think = Playerchecker_Think;
- playerchecker.nextthink = time + 0.2;
-
- Porto_Init();
- TrueAim_Init();
-
- postinit = true;
-}
-
-// CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function
-// Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
-float button_zoom;
-void Cmd_Sbar_SetFields(float);
-void Cmd_Sbar_Help(float);
-float CSQC_ConsoleCommand(string strMessage)
-{
- float argc;
- // Tokenize String
- //argc = tokenize(strMessage);
- argc = tokenize_console(strMessage);
-
- // Acquire Command
- local string strCmd;
- strCmd = argv(0);
-
- if(strCmd == "+button4") { // zoom
- // return false, because the message shall be sent to the server anyway (for demos/speccing)
- if(ignore_plus_zoom)
- {
- --ignore_plus_zoom;
- return false;
- }
- button_zoom = 1;
- return true;
- } else if(strCmd == "-button4") { // zoom
- if(ignore_minus_zoom)
- {
- --ignore_minus_zoom;
- return false;
- }
- button_zoom = 0;
- return true;
- } else if(strCmd == "+button3") { // secondary
- button_attack2 = 1;
- return false;
- } else if(strCmd == "-button3") { // secondary
- button_attack2 = 0;
- return false;
- } else if(strCmd == "+showscores") {
- sb_showscores = true;
- return true;
- } else if(strCmd == "-showscores") {
- sb_showscores = false;
- return true;
- } else if(strCmd == "+showaccuracy") {
- sb_showaccuracy = true;
- return true;
- } else if(strCmd == "-showaccuracy") {
- sb_showaccuracy = false;
- return true;
- }
-
- if(camera_active)
- if(strCmd == "+forward" || strCmd == "-back") {
- ++camera_direction_x;
- return true;
- } else if(strCmd == "-forward" || strCmd == "+back") {
- --camera_direction_x;
- return true;
- } else if(strCmd == "+moveright" || strCmd == "-moveleft") {
- --camera_direction_y;
- return true;
- } else if(strCmd == "-moveright" || strCmd == "+moveleft") {
- ++camera_direction_y;
- return true;
- } else if(strCmd == "+moveup" || strCmd == "-movedown") {
- ++camera_direction_z;
- return true;
- } else if(strCmd == "-moveup" || strCmd == "+movedown") {
- --camera_direction_z;
- return true;
- } else if(strCmd == "+roll_right" || strCmd == "-roll_left") {
- ++camera_roll;
- return true;
- } else if(strCmd == "+roll_left" || strCmd == "-roll_right") {
- --camera_roll;
- return true;
- }
-
- return false;
-}
-
-.vector view_ofs;
-entity debug_shotorg;
-void ShotOrg_Draw()
-{
- self.origin = view_origin + view_forward * self.view_ofs_x + view_right * self.view_ofs_y + view_up * self.view_ofs_z;
- self.angles = view_angles;
- self.angles_x = -self.angles_x;
- if not(self.cnt)
- R_AddEntity(self);
-}
-void ShotOrg_Draw2D()
-{
- vector coord2d_topleft, coord2d_topright, coord2d;
- string s;
- vector fs;
-
- s = vtos(self.view_ofs);
- s = substring(s, 1, strlen(s) - 2);
- if(tokenize_console(s) == 3)
- s = strcat(argv(0), " ", argv(1), " ", argv(2));
-
- coord2d_topleft = project_3d_to_2d(self.origin + view_up * 4 - view_right * 4);
- coord2d_topright = project_3d_to_2d(self.origin + view_up * 4 + view_right * 4);
-
- fs = '1 1 0' * ((coord2d_topright_x - coord2d_topleft_x) / stringwidth(s, FALSE));
-
- coord2d = coord2d_topleft;
- if(fs_x < 8)
- {
- coord2d_x += (coord2d_topright_x - coord2d_topleft_x) * (1 - 8 / fs_x) * 0.5;
- fs = '8 8 0';
- }
- coord2d_y -= fs_y;
- coord2d_z = 0;
- drawstring(coord2d, s, fs, '1 1 1', 1, 0);
-}
-
-void ShotOrg_Spawn()
-{
- debug_shotorg = spawn();
- debug_shotorg.draw = ShotOrg_Draw;
- debug_shotorg.draw2d = ShotOrg_Draw2D;
- debug_shotorg.renderflags = RF_VIEWMODEL;
- debug_shotorg.effects = EF_FULLBRIGHT;
- precache_model("models/shotorg_adjuster.md3");
- setmodel(debug_shotorg, "models/shotorg_adjuster.md3");
- debug_shotorg.scale = 2;
- debug_shotorg.view_ofs = '25 8 -8';
-}
-
-void GameCommand(string msg)
-{
- float argc;
- argc = tokenize_console(msg);
-
- if(argv(0) == "help" || argc == 0)
- {
- print("Usage: cl_cmd COMMAND..., where possible commands are:\n");
- print(" settemp cvar value\n");
- print(" radar\n");
- print(" sbar_columns_set ...\n");
- print(" sbar_columns_help\n");
- GameCommand_Generic("help");
- return;
- }
-
- if(GameCommand_Generic(msg))
- return;
-
- string cmd;
- cmd = argv(0);
- if(cmd == "mv_download") {
- Cmd_MapVote_MapDownload(argc);
- }
- else if(cmd == "settemp") {
- cvar_clientsettemp(argv(1), argv(2));
- }
- else if(cmd == "radar") {
- ons_showmap = !ons_showmap;
- }
- else if(cmd == "sbar_columns_set") {
- Cmd_Sbar_SetFields(argc);
- }
- else if(cmd == "sbar_columns_help") {
- Cmd_Sbar_Help(argc);
- }
-#ifdef BLURTEST
- else if(cmd == "blurtest") {
- blurtest_time0 = time;
- blurtest_time1 = time + stof(argv(1));
- blurtest_radius = stof(argv(2));
- blurtest_power = stof(argv(3));
- }
-#endif
- else if(cmd == "shotorg_move") {
- if(!debug_shotorg)
- ShotOrg_Spawn();
- else
- debug_shotorg.view_ofs = debug_shotorg.view_ofs + stov(argv(1));
- localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
- }
- else if(cmd == "shotorg_movez") {
- if(!debug_shotorg)
- ShotOrg_Spawn();
- else
- debug_shotorg.view_ofs = debug_shotorg.view_ofs + stof(argv(1)) * (debug_shotorg.view_ofs * (1 / debug_shotorg.view_ofs_x)); // closer/farther, same xy pos
- localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
- }
- else if(cmd == "shotorg_set") {
- if(!debug_shotorg)
- ShotOrg_Spawn();
- else
- debug_shotorg.view_ofs = stov(argv(1));
- localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
- }
- else if(cmd == "shotorg_setz") {
- if(!debug_shotorg)
- ShotOrg_Spawn();
- else
- debug_shotorg.view_ofs = debug_shotorg.view_ofs * (stof(argv(1)) / debug_shotorg.view_ofs_x); // closer/farther, same xy pos
- localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
- }
- else if(cmd == "shotorg_toggle_hide") {
- if(debug_shotorg)
- {
- debug_shotorg.cnt = !debug_shotorg.cnt;
- }
- }
- else if(cmd == "shotorg_end") {
- if(debug_shotorg)
- {
- print(vtos(debug_shotorg.view_ofs), "\n");
- remove(debug_shotorg);
- debug_shotorg = world;
- }
- localcmd("sv_cmd debug_shotorg\n");
- }
- else
- {
- print("Invalid command. For a list of supported commands, try cl_cmd help.\n");
- }
-
- return;
-}
-
-// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
-// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
-// All keys are in ascii.
-// bInputType = 0 is key pressed, 1 is key released, 2 is mouse input.
-// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
-// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
-float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
-{
- local float bSkipKey;
- bSkipKey = false;
-
- if(menu_visible)
- if(menu_action(bInputType, nPrimary, nSecondary))
- return TRUE;
- return bSkipKey;
-}
-
-// END REQUIRED CSQC FUNCTIONS
-// --------------------------------------------------------------------------
-
-// --------------------------------------------------------------------------
-// BEGIN OPTIONAL CSQC FUNCTIONS
-void Ent_ReadEntCS()
-{
- InterpolateOrigin_Undo();
-
- self.classname = "entcs_receiver";
- self.sv_entnum = ReadByte() - 1;
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
- self.angles_y = ReadByte() * 360.0 / 256;
- self.origin_z = self.angles_x = self.angles_z = 0;
-
- InterpolateOrigin_Note();
-}
-
-void Ent_Remove();
-
-void Ent_RemovePlayerScore()
-{
- float i;
-
- if(self.owner)
- {
- SetTeam(self.owner, -1);
- self.owner.gotscores = 0;
- for(i = 0; i < MAX_SCORE; ++i)
- self.owner.(scores[i]) = 0; // clear all scores
- }
-}
-
-void Ent_ReadPlayerScore()
-{
- float i, n;
- float isNew;
- entity o;
-
- // damnit -.- don't want to go change every single .sv_entnum in sbar.qc AGAIN
- // (no I've never heard of M-x replace-string, sed, or anything like that)
- isNew = !self.owner; // workaround for DP bug
- n = ReadByte()-1;
-
-#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- if(!isNew && n != self.sv_entnum)
- {
- print("A CSQC entity changed its owner!\n");
- isNew = true;
- Ent_Remove();
- self.enttype = ENT_CLIENT_SCORES;
- }
-#endif
-
- self.sv_entnum = n;
-
- if not(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)
- // RegisterPlayer(o);
- //playerchecker will do this for us later, if it has not already done so
-
-#if MAX_SCORE <= 3
- for(i = 0; i < MAX_SCORE; ++i)
- o.(scores[i]) = ReadShort();
-#else
- float sf;
-#if MAX_SCORE <= 8
- sf = ReadByte();
-#else
- sf = ReadShort();
-#endif
- float p;
- for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
- if(sf & p)
- o.(scores[i]) = ReadShort();
-#endif
-
- if(o.sort_prev)
- Sbar_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
-
- self.entremove = Ent_RemovePlayerScore;
-}
-
-void Ent_ReadTeamScore()
-{
- float i;
- entity o;
-
- self.team = ReadByte();
- o = self.owner = GetTeam(self.team, true);
-
-#if MAX_TEAMSCORE <= 3
- for(i = 0; i < MAX_TEAMSCORE; ++i)
- o.(teamscores[i]) = ReadShort();
-#else
- float sf;
-#if MAX_TEAMSCORE <= 8
- sf = ReadByte();
-#else
- sf = ReadShort();
-#endif
- float p;
- for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
- if(sf & p)
- o.(teamscores[i]) = ReadShort();
-#endif
-
- Sbar_UpdateTeamPos(o);
-}
-
-void Net_Reset()
-{
-}
-
-void Ent_ClientData()
-{
- float f;
- float newspectatee_status;
-
- f = ReadByte();
-
- sb_showscores_force = (f & 1);
-
- if(f & 2)
- {
- newspectatee_status = ReadByte();
- if(newspectatee_status == player_localentnum)
- newspectatee_status = -1; // observing
- }
- else
- newspectatee_status = 0;
-
- spectatorbutton_zoom = (f & 4);
-
- if(f & 8)
- {
- angles_held_status = 1;
- angles_held_x = ReadAngle();
- angles_held_y = ReadAngle();
- angles_held_z = 0;
- }
- else
- angles_held_status = 0;
-
- if(newspectatee_status != spectatee_status)
- {
- // clear race stuff
- race_laptime = 0;
- race_checkpointtime = 0;
- }
- spectatee_status = newspectatee_status;
-}
-
-void Ent_Nagger()
-{
- float nags, i, j, b, f;
-
- nags = ReadByte();
-
- if(nags & 128)
- {
- if(vote_called_vote)
- strunzone(vote_called_vote);
- vote_called_vote = strzone(ColorTranslateRGB(ReadString()));
- }
-
- if(nags & 1)
- {
- for(j = 0; j < maxclients; ++j)
- if(playerslots[j])
- playerslots[j].ready = 1;
- for(i = 1; i <= maxclients; i += 8)
- {
- f = ReadByte();
- for(j = i-1, b = 1; b < 256; b *= 2, ++j)
- if not(f & b)
- if(playerslots[j])
- playerslots[j].ready = 0;
- }
- }
-
- ready_waiting = (nags & 1);
- ready_waiting_for_me = (nags & 2);
- vote_waiting = (nags & 4);
- vote_waiting_for_me = (nags & 8);
- warmup_stage = (nags & 16);
-}
-
-void Ent_RandomSeed()
-{
- float s;
- prandom_debug();
- s = ReadShort();
- psrandom(s);
-}
-
-// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
-// The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
-void Ent_RadarLink();
-void Ent_Init();
-void Ent_ScoresInfo();
-void(float bIsNewEntity) CSQC_Ent_Update =
-{
- float t;
- float savetime;
- t = ReadByte();
-
- // set up the "time" global for received entities to be correct for interpolation purposes
- savetime = time;
- if(servertime)
- {
- time = servertime;
- }
- else
- {
- serverprevtime = time;
- serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
- time = serverprevtime + serverdeltatime;
- }
-
-#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- if(self.enttype)
- if(t != self.enttype)
- {
- print("A CSQC entity changed its type!\n");
- Ent_Remove();
- }
-#endif
- self.enttype = t;
- switch(t)
- {
- case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break;
- case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break;
- case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break;
- case ENT_CLIENT_POINTPARTICLES: Ent_PointParticles(); break;
- case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break;
- case ENT_CLIENT_LASER: Ent_Laser(); break;
- case ENT_CLIENT_NAGGER: Ent_Nagger(); break;
- case ENT_CLIENT_WAYPOINT: Ent_WaypointSprite(); break;
- case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break;
- case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break;
- case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(); break;
- case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(); break;
- case ENT_CLIENT_CASING: Ent_Casing(); break;
- case ENT_CLIENT_INIT: Ent_Init(); break;
- case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break;
- case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break;
- case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break;
- case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break;
- case ENT_CLIENT_WALL: Ent_Wall(); break;
- default:
- error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n"));
- break;
- }
-
- time = savetime;
-};
-// Destructor, but does NOT deallocate the entity by calling remove(). Also
-// used when an entity changes its type. For an entity that someone interacts
-// with others, make sure it can no longer do so.
-void Ent_Remove()
-{
- if(self.entremove)
- self.entremove();
-
- self.enttype = 0;
- self.classname = "";
- self.draw = menu_sub_null;
- self.entremove = menu_sub_null;
- // TODO possibly set more stuff to defaults
-}
-// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well.
-void CSQC_Ent_Remove()
-{
- if(self.enttype)
- Ent_Remove();
- remove(self);
-}
-
-void Gamemode_Init()
-{
- if(gametype == GAME_ONSLAUGHT) {
- print(strcat("Using ", minimapname, " as minimap.\n"));
- precache_pic("gfx/ons-cp-neutral.tga");
- precache_pic("gfx/ons-cp-red.tga");
- precache_pic("gfx/ons-cp-blue.tga");
- precache_pic("gfx/ons-frame.tga");
- precache_pic("gfx/ons-frame-team.tga");
- } else if(gametype == GAME_KEYHUNT) {
- precache_pic("gfx/sb_key_carrying");
- precache_pic("gfx/sb_key_carrying_outline");
- }
-}
-// CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string.
-void CSQC_Parse_StuffCmd(string strMessage)
-{
- localcmd(strMessage);
-}
-// CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string.
-void CSQC_Parse_Print(string strMessage)
-{
- print(ColorTranslateRGB(strMessage));
-}
-
-// CSQC_Parse_CenterPrint : Provides the centerprint string in the first parameter that the server provided.
-void CSQC_Parse_CenterPrint(string strMessage)
-{
- centerprint(strMessage);
-}
-
-void Fog_Force()
-{
- // TODO somehow thwart prvm_globalset client ...
-
- if(forcefog != "")
- localcmd(strcat("\nfog ", forcefog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
-}
-
-void Gamemode_Init();
-void Ent_ScoresInfo()
-{
- float i;
- self.classname = "ent_client_scores_info";
- gametype = ReadByte();
- for(i = 0; i < MAX_SCORE; ++i)
- {
- scores_label[i] = strzone(ReadString());
- scores_flags[i] = ReadByte();
- }
- for(i = 0; i < MAX_TEAMSCORE; ++i)
- {
- teamscores_label[i] = strzone(ReadString());
- teamscores_flags[i] = ReadByte();
- }
- Sbar_InitScores();
- Gamemode_Init();
-}
-
-void Ent_Init()
-{
- float i;
- self.classname = "ent_client_init";
-
- nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
-
- for(i = 0; i < 24; ++i)
- weaponimpulse[i] = ReadByte() - 1;
- hook_shotorigin_x = ReadCoord();
- hook_shotorigin_y = ReadCoord();
- hook_shotorigin_z = ReadCoord();
-
- if(forcefog)
- strunzone(forcefog);
- forcefog = strzone(ReadString());
-
- armorblockpercent = ReadByte() / 255.0;
-
- if(!postinit)
- PostInit();
-}
-
-void Net_ReadRace()
-{
- float b;
-
- b = ReadByte();
-
- switch(b)
- {
- case RACE_NET_CHECKPOINT_HIT_QUALIFYING:
- race_checkpoint = ReadByte();
- race_time = ReadShort();
- race_previousbesttime = ReadShort();
- if(race_previousbestname)
- strunzone(race_previousbestname);
- race_previousbestname = strzone(ColorTranslateRGB(ReadString()));
-
- race_checkpointtime = time;
-
- if(race_checkpoint == 0)
- race_laptime = time; // valid
-
- break;
-
- case RACE_NET_CHECKPOINT_CLEAR:
- race_laptime = 0;
- race_checkpointtime = 0;
- break;
-
- case RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING:
- race_laptime = ReadCoord();
- race_checkpointtime = -99999;
- // fall through
- case RACE_NET_CHECKPOINT_NEXT_QUALIFYING:
- race_nextcheckpoint = ReadByte();
-
- race_nextbesttime = ReadShort();
- if(race_nextbestname)
- strunzone(race_nextbestname);
- race_nextbestname = strzone(ColorTranslateRGB(ReadString()));
- break;
-
- case RACE_NET_CHECKPOINT_HIT_RACE:
- race_mycheckpoint = ReadByte();
- race_mycheckpointtime = time;
- race_mycheckpointdelta = ReadShort();
- race_mycheckpointlapsdelta = ReadByte();
- if(race_mycheckpointlapsdelta >= 128)
- race_mycheckpointlapsdelta -= 256;
- if(race_mycheckpointenemy)
- strunzone(race_mycheckpointenemy);
- race_mycheckpointenemy = strzone(ColorTranslateRGB(ReadString()));
- break;
-
- case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT:
- race_othercheckpoint = ReadByte();
- race_othercheckpointtime = time;
- race_othercheckpointdelta = ReadShort();
- race_othercheckpointlapsdelta = ReadByte();
- if(race_othercheckpointlapsdelta >= 128)
- race_othercheckpointlapsdelta -= 256;
- if(race_othercheckpointenemy)
- strunzone(race_othercheckpointenemy);
- race_othercheckpointenemy = strzone(ColorTranslateRGB(ReadString()));
- break;
- }
-}
-
-void Net_ReadSpawn()
-{
- zoomin_effect = 1;
- current_viewzoom = 0.6;
-}
-
-// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
-// You must ALWAYS first acquire the temporary ID, which is sent as a byte.
-// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
-float CSQC_Parse_TempEntity()
-{
- local float bHandled;
- bHandled = true;
- // Acquire TE ID
- local float nTEID;
- nTEID = ReadByte();
-
- // NOTE: Could just do return instead of break...
- switch(nTEID)
- {
- case TE_CSQC_PICTURE:
- Net_MapVote_Picture();
- bHandled = true;
- break;
- case TE_CSQC_RACE:
- Net_ReadRace();
- bHandled = true;
- break;
- case 13: // TE_BEAM
- Net_GrapplingHook();
- bHandled = true;
- break;
- case TE_CSQC_SPAWN:
- Net_ReadSpawn();
- bHandled = true;
- break;
- case TE_CSQC_ZCURVEPARTICLES:
- Net_ReadZCurveParticles();
- bHandled = true;
- break;
- case TE_CSQC_NEXGUNBEAMPARTICLE:
- Net_ReadNexgunBeamParticle();
- bHandled = true;
- break;
- case TE_CSQC_LIGHTNINGARC:
- Net_ReadLightningarc();
- bHandled = true;
- break;
- default:
- // No special logic for this temporary entity; return 0 so the engine can handle it
- bHandled = false;
- break;
- }
-
- return bHandled;
-}
-
-string getcommandkey(string text, string command)
-{
- string keys;
- float n, j, k, l;
-
- if (!sbar_showbinds)
- return text;
-
- keys = db_get(binddb, command);
- if (!keys)
- {
- n = tokenize(findkeysforcommand(command)); // uses '...' strings
- for(j = 0; j < n; ++j)
- {
- k = stof(argv(j));
- if(k != -1)
- {
- if ("" == keys)
- keys = keynumtostring(k);
- else
- keys = strcat(keys, ", ", keynumtostring(k));
-
- ++l;
- if (sbar_showbinds_limit > 0 && sbar_showbinds_limit >= l) break;
- }
-
- }
- db_put(binddb, command, keys);
- }
-
- if ("" == keys) {
- if (sbar_showbinds > 1)
- return strcat(text, " (not bound)");
- else
- return text;
- }
- else if (sbar_showbinds > 1)
- return strcat(text, " (", keys, ")");
- else
- return keys;
-}
+// --------------------------------------------------------------------------
+// BEGIN REQUIRED CSQC FUNCTIONS
+//include "main.qh"
+
+#define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+
+void cvar_clientsettemp(string cv, string val)
+{
+ entity e;
+ for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+ if(e.netname == cv)
+ goto saved;
+ e = spawn();
+ e.classname = "saved_cvar_value";
+ e.netname = strzone(cv);
+ e.message = strzone(cvar_string(cv));
+:saved
+ cvar_set(cv, val);
+}
+
+void cvar_clientsettemp_restore()
+{
+ entity e;
+ for(e = world; (e = find(e, classname, "saved_cvar_value")); )
+ cvar_set(e.netname, e.message);
+}
+
+void() menu_show_error =
+{
+ drawstring('0 200 0', "ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!", '8 8 0', '1 0 0', 1, 0);
+};
+
+// CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
+// Useful for precaching things
+
+void() menu_sub_null =
+{
+};
+
+#ifdef USE_FTE
+float __engine_check;
+#endif
+
+string forcefog;
+void WaypointSprite_Load();
+void CSQC_Init(void)
+{
+#ifdef USE_FTE
+#pragma target ID
+ __engine_check = checkextension("DP_SV_WRITEPICTURE");
+ if(!__engine_check)
+ {
+ print("^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n");
+ localcmd("\ndisconnect\n");
+ return;
+ }
+#pragma target FTE
+#endif
+
+ check_unacceptable_compiler_bugs();
+
+ float i;
+ CSQC_CheckEngine();
+ dprint_load();
+
+ binddb = db_create();
+ tempdb = db_create();
+ compressShortVector_init();
+
+ drawfont = 0;
+ menu_visible = FALSE;
+ menu_show = menu_show_error;
+ menu_action = menu_sub_null;
+
+ for(i = 0; i < 255; ++i)
+ if(getplayerkey(i, "viewentity") == "")
+ break;
+ maxclients = i;
+
+ //ctf_temp_1 = "";
+ // localcmd("alias order \"cmd order $*\""); enable if ctf-command thingy is used
+ //registercmd("ctf_menu");
+ registercmd("ons_map");
+ //registercmd("menu_action");
+
+ registercmd("+button3");
+ registercmd("-button3");
+ registercmd("+button4");
+ registercmd("-button4");
+ registercmd("+showaccuracy");registercmd("-showaccuracy");
+
+#ifndef CAMERATEST
+ if(isdemo())
+ {
+#endif
+ registercmd("+forward");registercmd("-forward");
+ registercmd("+back");registercmd("-back");
+ registercmd("+moveup");registercmd("-moveup");
+ registercmd("+movedown");registercmd("-movedown");
+ registercmd("+moveright");registercmd("-moveright");
+ registercmd("+moveleft");registercmd("-moveleft");
+ registercmd("+roll_right");registercmd("-roll_right");
+ registercmd("+roll_left");registercmd("-roll_left");
+#ifndef CAMERATEST
+ }
+#endif
+ registercvar("sbar_usecsqc", "1");
+ registercvar("sbar_columns", "default", CVAR_SAVE);
+
+ gametype = 0;
+
+ // sbar_fields uses strunzone on the titles!
+ for(i = 0; i < MAX_SBAR_FIELDS; ++i)
+ sbar_title[i] = strzone("(null)");
+
+ postinit = false;
+
+ teams = Sort_Spawn();
+ players = Sort_Spawn();
+
+ GetTeam(COLOR_SPECTATOR, true); // add specs first
+
+ cvar_clientsettemp("_supports_weaponpriority", "1");
+
+
+
+
+ cs_project_is_b0rked = TRUE;
+ R_SetView(VF_VIEWPORT, '0 0 0', '640 480 0');
+ R_SetView(VF_FOV, '90 90 0');
+ R_SetView(VF_ORIGIN, '0 0 0');
+ R_SetView(VF_ANGLES, '0 0 0');
+ R_SetView(VF_PERSPECTIVE, 1);
+ makevectors('0 0 0');
+ vector v;
+ v = cs_project(v_forward);
+ if(v_x - 320 < +1)
+ if(v_x - 320 > -1)
+ if(v_y - 240 < +1)
+ if(v_y - 240 > -1)
+ cs_project_is_b0rked = FALSE;
+
+ RegisterWeapons();
+
+ WaypointSprite_Load();
+
+ Projectile_Precache();
+ GibSplash_Precache();
+ Casings_Precache();
+ DamageInfo_Precache();
+ Announcer_Precache();
+
+ get_mi_min_max_texcoords(1); // try the CLEVER way first
+ minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
+ shortmapname = mi_shortname;
+
+ if(precache_pic(minimapname) == "")
+ {
+ // but maybe we have a non-clever minimap
+ minimapname = strcat("gfx/", mi_shortname, "_mini.tga");
+ if(precache_pic(minimapname) == "")
+ minimapname = ""; // FAIL
+ else
+ get_mi_min_max_texcoords(0); // load new texcoords
+ }
+
+ mi_center = (mi_min + mi_max) * 0.5;
+ mi_scale = mi_max - mi_min;
+ minimapname = strzone(minimapname);
+}
+
+// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
+void CSQC_Shutdown(void)
+{
+#ifdef USE_FTE
+#pragma TARGET id
+ if(!__engine_check)
+ return 0;
+#pragma TARGET fte
+#endif
+
+ remove(teams);
+ remove(players);
+ db_close(binddb);
+ db_close(tempdb);
+
+ cvar_clientsettemp_restore();
+
+ if(camera_active)
+ cvar_set("chase_active",ftos(chase_active_backup));
+}
+
+.float has_team;
+float SetTeam(entity o, float Team)
+{
+ entity tm;
+ if(Team == -1) // leave
+ {
+ if(o.has_team)
+ {
+ //print("(DISCONNECT) leave team ", ftos(o.team), "\n");
+ tm = GetTeam(o.team, false);
+ tm.team_size -= 1;
+ o.has_team = 0;
+ return TRUE;
+ }
+ }
+ else
+ {
+ if not(o.has_team)
+ {
+ //print("(CONNECT) enter team ", ftos(o.team), "\n");
+ o.team = Team;
+ tm = GetTeam(Team, true);
+ tm.team_size += 1;
+ o.has_team = 1;
+ return TRUE;
+ }
+ else if(Team != o.team)
+ {
+ //print("(CHANGE) leave team ", ftos(o.team), "\n");
+ tm = GetTeam(o.team, false);
+ tm.team_size -= 1;
+ o.team = Team;
+ //print("(CHANGE) enter team ", ftos(o.team), "\n");
+ tm = GetTeam(Team, true);
+ tm.team_size += 1;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void Playerchecker_Think()
+{
+ float i;
+ entity e;
+ for(i = 0; i < maxclients; ++i)
+ {
+ e = playerslots[i];
+ if(GetPlayerName(i) == "")
+ {
+ if(e.sort_prev)
+ {
+ //print("playerchecker: KILL KILL KILL\n");
+ // player disconnected
+ SetTeam(e, -1);
+ RemovePlayer(e);
+ e.sort_prev = world;
+ //e.gotscores = 0;
+ }
+ }
+ else
+ {
+ if not(e.sort_prev)
+ {
+ //print("playerchecker: SPAWN SPAWN SPAWN\n");
+ // player connected
+ if not(e)
+ playerslots[i] = e = spawn();
+ e.sv_entnum = i;
+ //e.gotscores = 0; // we might already have the scores...
+ SetTeam(e, GetPlayerColor(i)); // will not hurt; later updates come with Sbar_UpdatePlayerTeams
+ RegisterPlayer(e);
+ Sbar_UpdatePlayerPos(e);
+ }
+ }
+ }
+ self.nextthink = time + 0.2;
+}
+
+void Porto_Init();
+void TrueAim_Init();
+void PostInit(void)
+{
+ print(strcat("PostInit\n maxclients = ", ftos(maxclients), "\n"));
+ localcmd(strcat("\nsbar_columns_set ", cvar_string("sbar_columns"), ";\n"));
+
+ entity playerchecker;
+ playerchecker = spawn();
+ playerchecker.think = Playerchecker_Think;
+ playerchecker.nextthink = time + 0.2;
+
+ Porto_Init();
+ TrueAim_Init();
+
+ postinit = true;
+}
+
+// CSQC_ConsoleCommand : Used to parse commands in the console that have been registered with the "registercmd" function
+// Return value should be 1 if CSQC handled the command, otherwise return 0 to have the engine handle it.
+float button_zoom;
+void Cmd_Sbar_SetFields(float);
+void Cmd_Sbar_Help(float);
+float CSQC_ConsoleCommand(string strMessage)
+{
+ float argc;
+ // Tokenize String
+ //argc = tokenize(strMessage);
+ argc = tokenize_console(strMessage);
+
+ // Acquire Command
+ local string strCmd;
+ strCmd = argv(0);
+
+ if(strCmd == "+button4") { // zoom
+ // return false, because the message shall be sent to the server anyway (for demos/speccing)
+ if(ignore_plus_zoom)
+ {
+ --ignore_plus_zoom;
+ return false;
+ }
+ button_zoom = 1;
+ return true;
+ } else if(strCmd == "-button4") { // zoom
+ if(ignore_minus_zoom)
+ {
+ --ignore_minus_zoom;
+ return false;
+ }
+ button_zoom = 0;
+ return true;
+ } else if(strCmd == "+button3") { // secondary
+ button_attack2 = 1;
+ return false;
+ } else if(strCmd == "-button3") { // secondary
+ button_attack2 = 0;
+ return false;
+ } else if(strCmd == "+showscores") {
+ sb_showscores = true;
+ return true;
+ } else if(strCmd == "-showscores") {
+ sb_showscores = false;
+ return true;
+ } else if(strCmd == "+showaccuracy") {
+ sb_showaccuracy = true;
+ return true;
+ } else if(strCmd == "-showaccuracy") {
+ sb_showaccuracy = false;
+ return true;
+ }
+
+ if(camera_active)
+ if(strCmd == "+forward" || strCmd == "-back") {
+ ++camera_direction_x;
+ return true;
+ } else if(strCmd == "-forward" || strCmd == "+back") {
+ --camera_direction_x;
+ return true;
+ } else if(strCmd == "+moveright" || strCmd == "-moveleft") {
+ --camera_direction_y;
+ return true;
+ } else if(strCmd == "-moveright" || strCmd == "+moveleft") {
+ ++camera_direction_y;
+ return true;
+ } else if(strCmd == "+moveup" || strCmd == "-movedown") {
+ ++camera_direction_z;
+ return true;
+ } else if(strCmd == "-moveup" || strCmd == "+movedown") {
+ --camera_direction_z;
+ return true;
+ } else if(strCmd == "+roll_right" || strCmd == "-roll_left") {
+ ++camera_roll;
+ return true;
+ } else if(strCmd == "+roll_left" || strCmd == "-roll_right") {
+ --camera_roll;
+ return true;
+ }
+
+ return false;
+}
+
+.vector view_ofs;
+entity debug_shotorg;
+void ShotOrg_Draw()
+{
+ self.origin = view_origin + view_forward * self.view_ofs_x + view_right * self.view_ofs_y + view_up * self.view_ofs_z;
+ self.angles = view_angles;
+ self.angles_x = -self.angles_x;
+ if not(self.cnt)
+ R_AddEntity(self);
+}
+void ShotOrg_Draw2D()
+{
+ vector coord2d_topleft, coord2d_topright, coord2d;
+ string s;
+ vector fs;
+
+ s = vtos(self.view_ofs);
+ s = substring(s, 1, strlen(s) - 2);
+ if(tokenize_console(s) == 3)
+ s = strcat(argv(0), " ", argv(1), " ", argv(2));
+
+ coord2d_topleft = project_3d_to_2d(self.origin + view_up * 4 - view_right * 4);
+ coord2d_topright = project_3d_to_2d(self.origin + view_up * 4 + view_right * 4);
+
+ fs = '1 1 0' * ((coord2d_topright_x - coord2d_topleft_x) / stringwidth(s, FALSE));
+
+ coord2d = coord2d_topleft;
+ if(fs_x < 8)
+ {
+ coord2d_x += (coord2d_topright_x - coord2d_topleft_x) * (1 - 8 / fs_x) * 0.5;
+ fs = '8 8 0';
+ }
+ coord2d_y -= fs_y;
+ coord2d_z = 0;
+ drawstring(coord2d, s, fs, '1 1 1', 1, 0);
+}
+
+void ShotOrg_Spawn()
+{
+ debug_shotorg = spawn();
+ debug_shotorg.draw = ShotOrg_Draw;
+ debug_shotorg.draw2d = ShotOrg_Draw2D;
+ debug_shotorg.renderflags = RF_VIEWMODEL;
+ debug_shotorg.effects = EF_FULLBRIGHT;
+ precache_model("models/shotorg_adjuster.md3");
+ setmodel(debug_shotorg, "models/shotorg_adjuster.md3");
+ debug_shotorg.scale = 2;
+ debug_shotorg.view_ofs = '25 8 -8';
+}
+
+void GameCommand(string msg)
+{
+ float argc;
+ argc = tokenize_console(msg);
+
+ if(argv(0) == "help" || argc == 0)
+ {
+ print("Usage: cl_cmd COMMAND..., where possible commands are:\n");
+ print(" settemp cvar value\n");
+ print(" radar\n");
+ print(" sbar_columns_set ...\n");
+ print(" sbar_columns_help\n");
+ GameCommand_Generic("help");
+ return;
+ }
+
+ if(GameCommand_Generic(msg))
+ return;
+
+ string cmd;
+ cmd = argv(0);
+ if(cmd == "mv_download") {
+ Cmd_MapVote_MapDownload(argc);
+ }
+ else if(cmd == "settemp") {
+ cvar_clientsettemp(argv(1), argv(2));
+ }
+ else if(cmd == "radar") {
+ ons_showmap = !ons_showmap;
+ }
+ else if(cmd == "sbar_columns_set") {
+ Cmd_Sbar_SetFields(argc);
+ }
+ else if(cmd == "sbar_columns_help") {
+ Cmd_Sbar_Help(argc);
+ }
+#ifdef BLURTEST
+ else if(cmd == "blurtest") {
+ blurtest_time0 = time;
+ blurtest_time1 = time + stof(argv(1));
+ blurtest_radius = stof(argv(2));
+ blurtest_power = stof(argv(3));
+ }
+#endif
+ else if(cmd == "shotorg_move") {
+ if(!debug_shotorg)
+ ShotOrg_Spawn();
+ else
+ debug_shotorg.view_ofs = debug_shotorg.view_ofs + stov(argv(1));
+ localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
+ }
+ else if(cmd == "shotorg_movez") {
+ if(!debug_shotorg)
+ ShotOrg_Spawn();
+ else
+ debug_shotorg.view_ofs = debug_shotorg.view_ofs + stof(argv(1)) * (debug_shotorg.view_ofs * (1 / debug_shotorg.view_ofs_x)); // closer/farther, same xy pos
+ localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
+ }
+ else if(cmd == "shotorg_set") {
+ if(!debug_shotorg)
+ ShotOrg_Spawn();
+ else
+ debug_shotorg.view_ofs = stov(argv(1));
+ localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
+ }
+ else if(cmd == "shotorg_setz") {
+ if(!debug_shotorg)
+ ShotOrg_Spawn();
+ else
+ debug_shotorg.view_ofs = debug_shotorg.view_ofs * (stof(argv(1)) / debug_shotorg.view_ofs_x); // closer/farther, same xy pos
+ localcmd("sv_cmd debug_shotorg \"", vtos(debug_shotorg.view_ofs), "\"\n");
+ }
+ else if(cmd == "shotorg_toggle_hide") {
+ if(debug_shotorg)
+ {
+ debug_shotorg.cnt = !debug_shotorg.cnt;
+ }
+ }
+ else if(cmd == "shotorg_end") {
+ if(debug_shotorg)
+ {
+ print(vtos(debug_shotorg.view_ofs), "\n");
+ remove(debug_shotorg);
+ debug_shotorg = world;
+ }
+ localcmd("sv_cmd debug_shotorg\n");
+ }
+ else
+ {
+ print("Invalid command. For a list of supported commands, try cl_cmd help.\n");
+ }
+
+ return;
+}
+
+// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
+// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
+// All keys are in ascii.
+// bInputType = 0 is key pressed, 1 is key released, 2 is mouse input.
+// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
+// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
+float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
+{
+ local float bSkipKey;
+ bSkipKey = false;
+
+ if(menu_visible)
+ if(menu_action(bInputType, nPrimary, nSecondary))
+ return TRUE;
+ return bSkipKey;
+}
+
+// END REQUIRED CSQC FUNCTIONS
+// --------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------
+// BEGIN OPTIONAL CSQC FUNCTIONS
+void Ent_ReadEntCS()
+{
+ InterpolateOrigin_Undo();
+
+ self.classname = "entcs_receiver";
+ self.sv_entnum = ReadByte() - 1;
+ self.origin_x = ReadShort();
+ self.origin_y = ReadShort();
+ self.origin_z = ReadShort();
+ self.angles_y = ReadByte() * 360.0 / 256;
+ self.origin_z = self.angles_x = self.angles_z = 0;
+
+ InterpolateOrigin_Note();
+}
+
+void Ent_Remove();
+
+void Ent_RemovePlayerScore()
+{
+ float i;
+
+ if(self.owner)
+ {
+ SetTeam(self.owner, -1);
+ self.owner.gotscores = 0;
+ for(i = 0; i < MAX_SCORE; ++i)
+ self.owner.(scores[i]) = 0; // clear all scores
+ }
+}
+
+void Ent_ReadPlayerScore()
+{
+ float i, n;
+ float isNew;
+ entity o;
+
+ // damnit -.- don't want to go change every single .sv_entnum in sbar.qc AGAIN
+ // (no I've never heard of M-x replace-string, sed, or anything like that)
+ isNew = !self.owner; // workaround for DP bug
+ n = ReadByte()-1;
+
+#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+ if(!isNew && n != self.sv_entnum)
+ {
+ print("A CSQC entity changed its owner!\n");
+ isNew = true;
+ Ent_Remove();
+ self.enttype = ENT_CLIENT_SCORES;
+ }
+#endif
+
+ self.sv_entnum = n;
+
+ if not(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)
+ // RegisterPlayer(o);
+ //playerchecker will do this for us later, if it has not already done so
+
+#if MAX_SCORE <= 3
+ for(i = 0; i < MAX_SCORE; ++i)
+ o.(scores[i]) = ReadShort();
+#else
+ float sf;
+#if MAX_SCORE <= 8
+ sf = ReadByte();
+#else
+ sf = ReadShort();
+#endif
+ float p;
+ for(i = 0, p = 1; i < MAX_SCORE; ++i, p *= 2)
+ if(sf & p)
+ o.(scores[i]) = ReadShort();
+#endif
+
+ if(o.sort_prev)
+ Sbar_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
+
+ self.entremove = Ent_RemovePlayerScore;
+}
+
+void Ent_ReadTeamScore()
+{
+ float i;
+ entity o;
+
+ self.team = ReadByte();
+ o = self.owner = GetTeam(self.team, true);
+
+#if MAX_TEAMSCORE <= 3
+ for(i = 0; i < MAX_TEAMSCORE; ++i)
+ o.(teamscores[i]) = ReadShort();
+#else
+ float sf;
+#if MAX_TEAMSCORE <= 8
+ sf = ReadByte();
+#else
+ sf = ReadShort();
+#endif
+ float p;
+ for(i = 0, p = 1; i < MAX_TEAMSCORE; ++i, p *= 2)
+ if(sf & p)
+ o.(teamscores[i]) = ReadShort();
+#endif
+
+ Sbar_UpdateTeamPos(o);
+}
+
+void Net_Reset()
+{
+}
+
+void Ent_ClientData()
+{
+ float f;
+ float newspectatee_status;
+
+ f = ReadByte();
+
+ sb_showscores_force = (f & 1);
+
+ if(f & 2)
+ {
+ newspectatee_status = ReadByte();
+ if(newspectatee_status == player_localentnum)
+ newspectatee_status = -1; // observing
+ }
+ else
+ newspectatee_status = 0;
+
+ spectatorbutton_zoom = (f & 4);
+
+ if(f & 8)
+ {
+ angles_held_status = 1;
+ angles_held_x = ReadAngle();
+ angles_held_y = ReadAngle();
+ angles_held_z = 0;
+ }
+ else
+ angles_held_status = 0;
+
+ if(newspectatee_status != spectatee_status)
+ {
+ // clear race stuff
+ race_laptime = 0;
+ race_checkpointtime = 0;
+ }
+ spectatee_status = newspectatee_status;
+}
+
+void Ent_Nagger()
+{
+ float nags, i, j, b, f;
+
+ nags = ReadByte();
+
+ if(nags & 128)
+ {
+ if(vote_called_vote)
+ strunzone(vote_called_vote);
+ vote_called_vote = strzone(ColorTranslateRGB(ReadString()));
+ }
+
+ if(nags & 1)
+ {
+ for(j = 0; j < maxclients; ++j)
+ if(playerslots[j])
+ playerslots[j].ready = 1;
+ for(i = 1; i <= maxclients; i += 8)
+ {
+ f = ReadByte();
+ for(j = i-1, b = 1; b < 256; b *= 2, ++j)
+ if not(f & b)
+ if(playerslots[j])
+ playerslots[j].ready = 0;
+ }
+ }
+
+ ready_waiting = (nags & 1);
+ ready_waiting_for_me = (nags & 2);
+ vote_waiting = (nags & 4);
+ vote_waiting_for_me = (nags & 8);
+ warmup_stage = (nags & 16);
+}
+
+void Ent_RandomSeed()
+{
+ float s;
+ prandom_debug();
+ s = ReadShort();
+ psrandom(s);
+}
+
+// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
+// The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
+void Ent_RadarLink();
+void Ent_Init();
+void Ent_ScoresInfo();
+void(float bIsNewEntity) CSQC_Ent_Update =
+{
+ float t;
+ float savetime;
+ t = ReadByte();
+
+ // set up the "time" global for received entities to be correct for interpolation purposes
+ savetime = time;
+ if(servertime)
+ {
+ time = servertime;
+ }
+ else
+ {
+ serverprevtime = time;
+ serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ time = serverprevtime + serverdeltatime;
+ }
+
+#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+ if(self.enttype)
+ if(t != self.enttype)
+ {
+ print("A CSQC entity changed its type!\n");
+ Ent_Remove();
+ }
+#endif
+ self.enttype = t;
+ switch(t)
+ {
+ case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break;
+ case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break;
+ case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break;
+ case ENT_CLIENT_POINTPARTICLES: Ent_PointParticles(); break;
+ case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break;
+ case ENT_CLIENT_LASER: Ent_Laser(); break;
+ case ENT_CLIENT_NAGGER: Ent_Nagger(); break;
+ case ENT_CLIENT_WAYPOINT: Ent_WaypointSprite(); break;
+ case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break;
+ case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break;
+ case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(); break;
+ case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(); break;
+ case ENT_CLIENT_CASING: Ent_Casing(); break;
+ case ENT_CLIENT_INIT: Ent_Init(); break;
+ case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break;
+ case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break;
+ case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break;
+ case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break;
+ case ENT_CLIENT_WALL: Ent_Wall(); break;
+ default:
+ error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n"));
+ break;
+ }
+
+ time = savetime;
+};
+// Destructor, but does NOT deallocate the entity by calling remove(). Also
+// used when an entity changes its type. For an entity that someone interacts
+// with others, make sure it can no longer do so.
+void Ent_Remove()
+{
+ if(self.entremove)
+ self.entremove();
+
+ self.enttype = 0;
+ self.classname = "";
+ self.draw = menu_sub_null;
+ self.entremove = menu_sub_null;
+ // TODO possibly set more stuff to defaults
+}
+// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well.
+void CSQC_Ent_Remove()
+{
+ if(self.enttype)
+ Ent_Remove();
+ remove(self);
+}
+
+void Gamemode_Init()
+{
+ if(gametype == GAME_ONSLAUGHT) {
+ print(strcat("Using ", minimapname, " as minimap.\n"));
+ precache_pic("gfx/ons-cp-neutral.tga");
+ precache_pic("gfx/ons-cp-red.tga");
+ precache_pic("gfx/ons-cp-blue.tga");
+ precache_pic("gfx/ons-frame.tga");
+ precache_pic("gfx/ons-frame-team.tga");
+ } else if(gametype == GAME_KEYHUNT) {
+ precache_pic("gfx/sb_key_carrying");
+ precache_pic("gfx/sb_key_carrying_outline");
+ }
+}
+// CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string.
+void CSQC_Parse_StuffCmd(string strMessage)
+{
+ localcmd(strMessage);
+}
+// CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string.
+void CSQC_Parse_Print(string strMessage)
+{
+ print(ColorTranslateRGB(strMessage));
+}
+
+// CSQC_Parse_CenterPrint : Provides the centerprint string in the first parameter that the server provided.
+void CSQC_Parse_CenterPrint(string strMessage)
+{
+ centerprint(strMessage);
+}
+
+void Fog_Force()
+{
+ // TODO somehow thwart prvm_globalset client ...
+
+ if(forcefog != "")
+ localcmd(strcat("\nfog ", forcefog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
+}
+
+void Gamemode_Init();
+void Ent_ScoresInfo()
+{
+ float i;
+ self.classname = "ent_client_scores_info";
+ gametype = ReadByte();
+ for(i = 0; i < MAX_SCORE; ++i)
+ {
+ scores_label[i] = strzone(ReadString());
+ scores_flags[i] = ReadByte();
+ }
+ for(i = 0; i < MAX_TEAMSCORE; ++i)
+ {
+ teamscores_label[i] = strzone(ReadString());
+ teamscores_flags[i] = ReadByte();
+ }
+ Sbar_InitScores();
+ Gamemode_Init();
+}
+
+void Ent_Init()
+{
+ float i;
+ self.classname = "ent_client_init";
+
+ nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
+
+ for(i = 0; i < 24; ++i)
+ weaponimpulse[i] = ReadByte() - 1;
+ hook_shotorigin_x = ReadCoord();
+ hook_shotorigin_y = ReadCoord();
+ hook_shotorigin_z = ReadCoord();
+
+ if(forcefog)
+ strunzone(forcefog);
+ forcefog = strzone(ReadString());
+
+ armorblockpercent = ReadByte() / 255.0;
+
+ if(!postinit)
+ PostInit();
+}
+
+void Net_ReadRace()
+{
+ float b;
+
+ b = ReadByte();
+
+ switch(b)
+ {
+ case RACE_NET_CHECKPOINT_HIT_QUALIFYING:
+ race_checkpoint = ReadByte();
+ race_time = ReadShort();
+ race_previousbesttime = ReadShort();
+ if(race_previousbestname)
+ strunzone(race_previousbestname);
+ race_previousbestname = strzone(ColorTranslateRGB(ReadString()));
+
+ race_checkpointtime = time;
+
+ if(race_checkpoint == 0)
+ race_laptime = time; // valid
+
+ break;
+
+ case RACE_NET_CHECKPOINT_CLEAR:
+ race_laptime = 0;
+ race_checkpointtime = 0;
+ break;
+
+ case RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING:
+ race_laptime = ReadCoord();
+ race_checkpointtime = -99999;
+ // fall through
+ case RACE_NET_CHECKPOINT_NEXT_QUALIFYING:
+ race_nextcheckpoint = ReadByte();
+
+ race_nextbesttime = ReadShort();
+ if(race_nextbestname)
+ strunzone(race_nextbestname);
+ race_nextbestname = strzone(ColorTranslateRGB(ReadString()));
+ break;
+
+ case RACE_NET_CHECKPOINT_HIT_RACE:
+ race_mycheckpoint = ReadByte();
+ race_mycheckpointtime = time;
+ race_mycheckpointdelta = ReadShort();
+ race_mycheckpointlapsdelta = ReadByte();
+ if(race_mycheckpointlapsdelta >= 128)
+ race_mycheckpointlapsdelta -= 256;
+ if(race_mycheckpointenemy)
+ strunzone(race_mycheckpointenemy);
+ race_mycheckpointenemy = strzone(ColorTranslateRGB(ReadString()));
+ break;
+
+ case RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT:
+ race_othercheckpoint = ReadByte();
+ race_othercheckpointtime = time;
+ race_othercheckpointdelta = ReadShort();
+ race_othercheckpointlapsdelta = ReadByte();
+ if(race_othercheckpointlapsdelta >= 128)
+ race_othercheckpointlapsdelta -= 256;
+ if(race_othercheckpointenemy)
+ strunzone(race_othercheckpointenemy);
+ race_othercheckpointenemy = strzone(ColorTranslateRGB(ReadString()));
+ break;
+ }
+}
+
+void Net_ReadSpawn()
+{
+ zoomin_effect = 1;
+ current_viewzoom = 0.6;
+}
+
+// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
+// You must ALWAYS first acquire the temporary ID, which is sent as a byte.
+// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
+float CSQC_Parse_TempEntity()
+{
+ local float bHandled;
+ bHandled = true;
+ // Acquire TE ID
+ local float nTEID;
+ nTEID = ReadByte();
+
+ // NOTE: Could just do return instead of break...
+ switch(nTEID)
+ {
+ case TE_CSQC_PICTURE:
+ Net_MapVote_Picture();
+ bHandled = true;
+ break;
+ case TE_CSQC_RACE:
+ Net_ReadRace();
+ bHandled = true;
+ break;
+ case 13: // TE_BEAM
+ Net_GrapplingHook();
+ bHandled = true;
+ break;
+ case TE_CSQC_SPAWN:
+ Net_ReadSpawn();
+ bHandled = true;
+ break;
+ case TE_CSQC_ZCURVEPARTICLES:
+ Net_ReadZCurveParticles();
+ bHandled = true;
+ break;
+ case TE_CSQC_NEXGUNBEAMPARTICLE:
+ Net_ReadNexgunBeamParticle();
+ bHandled = true;
+ break;
+ case TE_CSQC_LIGHTNINGARC:
+ Net_ReadLightningarc();
+ bHandled = true;
+ break;
+ default:
+ // No special logic for this temporary entity; return 0 so the engine can handle it
+ bHandled = false;
+ break;
+ }
+
+ return bHandled;
+}
+
+string getcommandkey(string text, string command)
+{
+ string keys;
+ float n, j, k, l;
+
+ if (!sbar_showbinds)
+ return text;
+
+ keys = db_get(binddb, command);
+ if (!keys)
+ {
+ n = tokenize(findkeysforcommand(command)); // uses '...' strings
+ for(j = 0; j < n; ++j)
+ {
+ k = stof(argv(j));
+ if(k != -1)
+ {
+ if ("" == keys)
+ keys = keynumtostring(k);
+ else
+ keys = strcat(keys, ", ", keynumtostring(k));
+
+ ++l;
+ if (sbar_showbinds_limit > 0 && sbar_showbinds_limit >= l) break;
+ }
+
+ }
+ db_put(binddb, command, keys);
+ }
+
+ if ("" == keys) {
+ if (sbar_showbinds > 1)
+ return strcat(text, " (not bound)");
+ else
+ return text;
+ }
+ else if (sbar_showbinds > 1)
+ return strcat(text, " (", keys, ")");
+ else
+ return keys;
+}
Property changes on: trunk/data/qcsrc/client/Main.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/View.qc
===================================================================
--- trunk/data/qcsrc/client/View.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/View.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,863 +1,863 @@
-#define spider_rocket_icon "gfx/spiderbot/rocket_ico.tga"
-#define spider_rocket_targ "gfx/spiderbot/target.tga"
-#define SPIDER_CROSS "textures/spiderbot/cross.tga"
-#define rkt_size 32
-#define rld_size_x 256
-#define rld_size_y 16
-
-entity porto;
-vector polyline[16];
-float trace_dphitcontents;
-float trace_networkentity;
-float Q3SURFACEFLAG_SLICK = 2; // low friction surface
-float DPCONTENTS_SOLID = 1; // blocks player movement
-float DPCONTENTS_BODY = 32; // blocks player movement
-float DPCONTENTS_CORPSE = 64; // blocks player movement
-float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
-void Porto_Draw()
-{
- vector p, dir, ang, q, nextdir;
- float idx, portal_number, portal1_idx;
-
- if(activeweapon != WEP_PORTO || spectatee_status || gametype == GAME_NEXBALL)
- return;
- if(intermission == 1)
- return;
- if(intermission == 2)
- return;
- if (getstati(STAT_HEALTH) <= 0)
- return;
-
- dir = view_forward;
-
- if(angles_held_status)
- {
- makevectors(angles_held);
- dir = v_forward;
- }
-
- p = view_origin;
-
- polyline[0] = p;
- idx = 1;
- portal_number = 0;
- nextdir = dir;
-
- for(;;)
- {
- dir = nextdir;
- traceline(p, p + 65536 * dir, TRUE, porto);
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
- return;
- nextdir = dir - 2 * (dir * trace_plane_normal) * trace_plane_normal; // mirror dir at trace_plane_normal
- p = trace_endpos;
- polyline[idx] = p;
- ++idx;
- if(idx >= 16)
- return;
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
- continue;
- ++portal_number;
- ang = vectoangles2(trace_plane_normal, dir);
- ang_x = -ang_x;
- makevectors(ang);
- if(!CheckWireframeBox(porto, p - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
- return;
- if(portal_number == 1)
- portal1_idx = idx;
- if(portal_number >= 2)
- break;
- }
-
- while(idx >= 2)
- {
- p = polyline[idx-2];
- q = polyline[idx-1];
- if(idx == 2)
- p = p - view_up * 16;
- if(idx-1 >= portal1_idx)
- {
- Draw_CylindricLine(p, q, 4, "", 1, 0, '0 0 1', 0.5, DRAWFLAG_NORMAL);
- }
- else
- {
- Draw_CylindricLine(p, q, 4, "", 1, 0, '1 0 0', 0.5, DRAWFLAG_NORMAL);
- }
- --idx;
- }
-}
-
-/**
- * Checks whether the server initiated a map restart (stat_game_starttime changed)
- *
- * TODO: Use a better solution where a common shared entitiy is used that contains
- * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT
- * and STAT_FRAGLIMIT to be auto-sent)
- */
-void CheckForGamestartChange() {
- float startTime;
- startTime = getstatf(STAT_GAMESTARTTIME);
- if (previous_game_starttime != startTime) {
- if ((time + 5.0) < startTime) {
- //if connecting to server while restart was active don't always play prepareforbattle
- sound(self, CHAN_VOICE, "announcer/robotic/prepareforbattle.wav", VOL_BASEVOICE, ATTN_NONE);
- }
- if (time < startTime) {
- restartAnnouncer = spawn();
- restartAnnouncer.think = restartAnnouncer_Think;
- restartAnnouncer.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime
- }
- }
- previous_game_starttime = startTime;
-}
-
-void Porto_Init()
-{
- porto = spawn();
- porto.classname = "porto";
- porto.draw = Porto_Draw;
- porto.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
-}
-
-float drawtime;
-
-float tan(float x)
-{
- return sin(x) / cos(x);
-}
-float atan2(float y, float x)
-{
- vector v;
- v = '1 0 0' * x + '0 1 0' * y;
- v = vectoangles(v);
- return v_y * 0.01745329251994329576;
-}
-
-vector GetCurrentFov(float fov)
-{
- float zoomsensitivity, zoomspeed, zoomfactor, zoomdir;
-
- zoomsensitivity = cvar("cl_zoomsensitivity");
- zoomfactor = cvar("cl_zoomfactor");
- if(zoomfactor < 1 || zoomfactor > 16)
- zoomfactor = 2.5;
- zoomspeed = cvar("cl_zoomspeed");
- if(zoomspeed >= 0)
- if(zoomspeed < 0.5 || zoomspeed > 16)
- zoomspeed = 3.5;
-
- zoomdir = button_zoom;
- if(getstati(STAT_ACTIVEWEAPON) == WEP_NEX) // do NOT use switchweapon here
- zoomdir += button_attack2;
- if(spectatee_status > 0 || isdemo())
- {
- if(spectatorbutton_zoom)
- zoomdir = 0 + !zoomdir;
- // do not even THINK about removing this 0
- // _I_ know what I am doing
- // fteqcc does not
- }
-
- if(zoomdir)
- zoomin_effect = 0;
-
- if(zoomin_effect || camera_active)
- {
- current_viewzoom = min(1, current_viewzoom + drawframetime);
- }
- else
- {
- if(zoomspeed < 0) // instant zoom
- {
- if(zoomdir)
- current_viewzoom = 1 / zoomfactor;
- else
- current_viewzoom = 1;
- }
- else
- {
- if(zoomdir)
- current_viewzoom = 1 / bound(1, 1 / current_viewzoom + drawframetime * zoomspeed * (zoomfactor - 1), zoomfactor);
- else
- current_viewzoom = bound(1 / zoomfactor, current_viewzoom + drawframetime * zoomspeed * (1 - 1 / zoomfactor), 1);
- }
- }
-
- if(almost_equals(current_viewzoom, 1))
- current_zoomfraction = 0;
- else if(almost_equals(current_viewzoom, 1/zoomfactor))
- current_zoomfraction = 1;
- else
- current_zoomfraction = (current_viewzoom - 1) / (1/zoomfactor - 1);
-
- if(zoomsensitivity < 1)
- setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
- else
- setsensitivityscale(1);
-
- float frustumx, frustumy, fovx, fovy;
- frustumy = tan(fov * 0.00872664625997164788) * 0.75 * current_viewzoom;
- frustumx = frustumy * vid_width / vid_height / vid_pixelheight;
- fovx = atan2(frustumx, 1) / 0.00872664625997164788;
- fovy = atan2(frustumy, 1) / 0.00872664625997164788;
-
- return '1 0 0' * fovx + '0 1 0' * fovy;
-}
-
-// this function must match W_SetupShot!
-float zoomscript_caught;
-entity trueaim;
-
-#define SHOTTYPE_HITTEAM 1
-#define SHOTTYPE_HITOBSTRUCTION 2
-#define SHOTTYPE_HITWORLD 3
-#define SHOTTYPE_HITENEMY 4
-
-void TrueAim_Init()
-{
- trueaim = spawn();
- trueaim.classname = "trueaim";
- trueaim.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-}
-
-float EnemyHitCheck(vector start, vector mi, vector ma, vector end)
-{
- float t;
- tracebox(start, mi, ma, end, MOVE_NORMAL, trueaim);
- if(trace_networkentity < 1)
- return SHOTTYPE_HITWORLD;
- if(trace_networkentity > maxclients)
- return SHOTTYPE_HITWORLD;
- t = GetPlayerColor(trace_networkentity - 1);
- if(teamplay)
- if(t == myteam)
- return SHOTTYPE_HITTEAM;
- if(t == COLOR_SPECTATOR)
- return SHOTTYPE_HITWORLD;
- return SHOTTYPE_HITENEMY;
-}
-
-float TrueAimCheck()
-{
- float nudge = 1; // added to traceline target and subtracted from result
- vector vecs, trueaimpoint, w_shotorg;
- vector mi, ma, dv;
- float shottype;
-
- mi = ma = '0 0 0';
-
- switch(activeweapon)
- {
- case WEP_TUBA: // no aim
- case WEP_PORTO: // shoots from eye
- case WEP_HOOK: // no trueaim
- case WEP_GRENADE_LAUNCHER: // toss curve
- return SHOTTYPE_HITWORLD;
- case WEP_CAMPINGRIFLE:
- if(zoomscript_caught)
- return EnemyHitCheck(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * MAX_SHOT_DISTANCE);
- break;
- case WEP_ROCKET_LAUNCHER: // projectile has a size!
- mi = '-3 -3 -3';
- ma = '3 3 3';
- break;
- case WEP_SEEKER: // projectile has a size!
- mi = '-2 -2 -2';
- ma = '2 2 2';
- break;
- case WEP_ELECTRO: // projectile has a size!
- mi = '0 0 -3';
- ma = '0 0 -3';
- break;
- }
-
- vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
-
- traceline(view_origin, view_origin + view_forward * MAX_SHOT_DISTANCE, MOVE_NOMONSTERS, trueaim);
- trueaimpoint = trace_endpos;
-
- if(vecs_x > 0)
- vecs_y = -vecs_y;
- else
- vecs = '0 0 0';
-
- dv = view_right * vecs_y + view_up * vecs_z;
- w_shotorg = view_origin + dv;
-
- // now move the vecs forward as much as requested if possible
- tracebox(w_shotorg, mi, ma, w_shotorg + view_forward * (vecs_x + nudge), MOVE_NORMAL, trueaim); // FIXME this MOVE_NORMAL part will misbehave a little in csqc
- w_shotorg = trace_endpos - view_forward * nudge;
-
- shottype = EnemyHitCheck(w_shotorg, mi, ma, trueaimpoint);
- if(shottype != SHOTTYPE_HITWORLD)
- return shottype;
-
- // now test whether we will actually hit the trueaimpoint...
- tracebox(w_shotorg, mi, ma, trueaimpoint, MOVE_NOMONSTERS, trueaim);
-
- if(vlen(trace_endpos - trueaimpoint) > vlen(ma - mi) + 1)
- // yes, this is an ugly hack... but it seems good enough to find out whether the test hits the same place as the initial trace
- return SHOTTYPE_HITOBSTRUCTION;
-
- return SHOTTYPE_HITWORLD;
-}
-
-void CSQC_common_hud(void);
-
-void CSQC_kh_hud(void);
-void CSQC_ctf_hud(void);
-void PostInit(void);
-void CSQC_Demo_Camera();
-float Sbar_WouldDrawScoreboard ();
-float view_set;
-float camera_mode;
-string NextFrameCommand;
-void CSQC_spider_HUD();
-void CSQC_UpdateView(float w, float h)
-{
- entity e;
- float fov;
- float f, i, j;
-
- dprint_load();
- WaypointSprite_Load();
-
- myteam = GetPlayerColor(player_localentnum - 1);
-
- ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
-
- // Render the Scene
- if(!intermission || !view_set)
- {
- view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
- view_angles = input_angles;
- makevectors(view_angles);
- view_forward = v_forward;
- view_right = v_right;
- view_up = v_up;
- view_set = 1;
- }
-
- vid_width = w;
- vid_height = h;
-
-#ifdef BLURTEST
- if(time > blurtest_time0 && time < blurtest_time1)
- {
- float r, t;
-
- t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
- r = t * blurtest_radius;
- f = 1 / pow(t, blurtest_power) - 1;
-
- cvar_set("r_glsl_postprocess", "1");
- cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
- }
- else
- {
- cvar_set("r_glsl_postprocess", "0");
- cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
- }
-#endif
-
- Fog_Force();
-
- drawframetime = max(0.000001, time - drawtime);
- drawtime = time;
-
- // watch for gametype changes here...
- // in ParseStuffCMD the cmd isn't executed yet :/
- // might even be better to add the gametype to TE_CSQC_INIT...?
- if(!postinit)
- PostInit();
-
- CheckForGamestartChange();
- maptimeAnnouncer();
-
- fov = cvar("fov");
- if(button_zoom || fov <= 59.5)
- {
- if(!zoomscript_caught)
- {
- localcmd("+button4\n");
- zoomscript_caught = 1;
- ignore_plus_zoom += 1;
- }
- }
- else
- {
- if(zoomscript_caught)
- {
- localcmd("-button4\n");
- zoomscript_caught = 0;
- ignore_minus_zoom += 1;
- }
- }
-
- sbar_alpha_fg = cvar("sbar_alpha_fg" );
- sbar_currentammo = cvar("sbar_showcurrentammo");
- sbar_hudselector = cvar("sbar_hudselector");
- sbar_hud_accuracy = cvar("sbar_hud_accuracy");
- ColorTranslateMode = cvar("cl_stripcolorcodes");
- activeweapon = getstati(STAT_SWITCHWEAPON);
- f = cvar("teamplay");
- if(f != teamplay)
- {
- teamplay = f;
- Sbar_InitScores();
- }
-
- if(last_weapon != activeweapon) {
- weapontime = time;
- last_weapon = activeweapon;
- }
-
- // ALWAYS Clear Current Scene First
- R_ClearScene();
-
- // Assign Standard Viewflags
- // Draw the World (and sky)
- R_SetView(VF_DRAWWORLD, 1);
-
- // Set the console size vars
- vid_conwidth = cvar("vid_conwidth");
- vid_conheight = cvar("vid_conheight");
- vid_pixelheight = cvar("vid_pixelheight");
-
- R_SetView(VF_FOV, GetCurrentFov(fov));
-
- // Camera for demo playback
- if(camera_active)
- {
- if(cvar("camera_enable"))
- CSQC_Demo_Camera();
- else
- {
- cvar_set("chase_active", ftos(chase_active_backup));
- cvar_set("cl_demo_mousegrab", "0");
- camera_active = FALSE;
- }
- }
-#ifdef CAMERATEST
- else if(cvar("camera_enable"))
-#else
- else if(cvar("camera_enable") && isdemo())
-#endif
- {
- // Enable required Darkplaces cvars
- chase_active_backup = cvar("chase_active");
- cvar_set("chase_active", "2");
- cvar_set("cl_demo_mousegrab", "1");
- camera_active = TRUE;
- camera_mode = FALSE;
- }
-
- // Draw the Crosshair
- float scoreboard_active;
- scoreboard_active = Sbar_WouldDrawScoreboard();
- R_SetView(VF_DRAWCROSSHAIR, 0); //Make sure engine crosshairs are always hidden
-
- // Draw the Engine Status Bar (the default Quake HUD)
- R_SetView(VF_DRAWENGINESBAR, 0);
-
- // fetch this one only once per frame
- sbar_showbinds = cvar("sbar_showbinds");
- sbar_showbinds_limit = cvar("sbar_showbinds_limit");
-
- // Update the mouse position
- /*
- mousepos_x = vid_conwidth;
- mousepos_y = vid_conheight;
- mousepos = mousepos*0.5 + getmousepos();
- */
-
- R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
-
- e = self;
- for(self = world; (self = nextent(self)); )
- if(self.draw)
- self.draw();
- self = e;
- R_RenderScene();
-
- // now switch to 2D drawing mode by calling a 2D drawing function
- // then polygon drawing will draw as 2D stuff, and NOT get queued until the
- // next R_RenderScene call
- drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0);
-
- // Draw the mouse cursor
- // NOTE: drawpic must happen after R_RenderScene for some reason
- //drawpic(getmousepos(), "gfx/cursor.tga", '11 14 0', '1 1 1', 1, 0);
- //drawstring('50 50', ftos(game), '10 10 0', '1 1 1', 1, 0);
- //self = edict_num(player_localnum);
- //drawstring('0 0', vtos(pmove_org), '8 8 0', '1 1 1', 1, 0);
- //drawstring('0 8', strcat("ORG: ", vtos(self.origin), " state: ", ftos(self.ctf_state), " HP: ", ftos(self.health)), '8 8 0', '1 1 1', 1, 0);
- // as long as the ctf part isn't in, this is useless
- if(menu_visible)
- menu_show();
-
- /*if(gametype == GAME_CTF)
- {
- ctf_view();
- } else */
-
- // draw 2D entities
- e = self;
- for(self = world; (self = nextent(self)); )
- if(self.draw2d)
- self.draw2d();
- self = e;
-
- // draw radar
- if(
- ons_showmap
- ||
- (
- !scoreboard_active
- &&
- cvar_string("cl_teamradar") != "0"
- &&
- (
- cvar("cl_teamradar") == 2
- ||
- teamplay
- )
- )
- )
- teamradar_view();
-
- if (cvar("cl_showpressedkeys")) // draw pressed keys when spectating and playing
- {
- if(spectatee_status > 0 || cvar("cl_showpressedkeys") >= 2)
- Sbar_DrawPressedKeys();
- }
-
- if (cvar("cl_showspeed"))
- Sbar_ShowSpeed();
-
- // draw sbar
- if(cvar("r_letterbox") == 0)
- Sbar_DrawCenterPrint(); // draw centerprint messages even if viewsize >= 120
-
- float hud;
- hud = getstati(STAT_HUD);
- if(hud == HUD_SPIDEBOT)
- {
- vector sz;
- CSQC_spider_HUD();
- sz = drawgetimagesize(SPIDER_CROSS);
- sz_x *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
- sz_y *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
- drawpic('0.5 0 0' * (vid_conwidth - sz_x) + '0 0.5 0' * (vid_conheight - sz_y), SPIDER_CROSS, sz, '1 1 1', cvar_or("cl_vehicle_spiderbot_cross_alpha",0.6), DRAWFLAG_NORMAL);
- }
- else
- {
- if(cvar("r_letterbox") == 0)
- if(cvar("viewsize") < 120)
- CSQC_common_hud();
-
- // crosshair goes VERY LAST
- if(!scoreboard_active && !ons_showmap && !camera_active) {
- // TrueAim check
- float shottype;
-
- if(cvar("crosshair_hittest"))
- shottype = TrueAimCheck();
- else
- shottype = SHOTTYPE_HITWORLD;
-
- string wcross_style;
- wcross_style = cvar_string("crosshair");
-
- if (wcross_style != "0") {
- vector wcross_color, wcross_size;
- string wcross_wep, wcross_name;
- float wcross_alpha, wcross_sizefloat;
-
- wcross_color_x = cvar("crosshair_color_red");
- wcross_color_y = cvar("crosshair_color_green");
- wcross_color_z = cvar("crosshair_color_blue");
- wcross_alpha = cvar("crosshair_color_alpha");
- wcross_sizefloat = cvar("crosshair_size");
- if (cvar("crosshair_per_weapon")) {
- e = get_weaponinfo(activeweapon);
- if (e && e.netname != "")
- {
- wcross_wep = e.netname;
- wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
- if(wcross_style == "")
- wcross_style = e.netname;
-
- if(!cvar("crosshair_color_override"))
- {
- wcross_color_x = cvar(strcat("crosshair_", wcross_wep, "_color_red"));
- wcross_color_y = cvar(strcat("crosshair_", wcross_wep, "_color_green"));
- wcross_color_z = cvar(strcat("crosshair_", wcross_wep, "_color_blue"));
- }
-
- wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_color_alpha"));
- wcross_sizefloat *= cvar(strcat("crosshair_", wcross_wep, "_size"));
- }
- }
-
- wcross_name = strcat("gfx/crosshair", wcross_style);
-
- if(shottype == SHOTTYPE_HITENEMY)
- wcross_sizefloat *= cvar("crosshair_hittest"); // is not queried if hittest is 0
- if(shottype == SHOTTYPE_HITTEAM)
- wcross_sizefloat /= cvar("crosshair_hittest"); // is not queried if hittest is 0
-
- wcross_size = drawgetimagesize(wcross_name);
- wcross_size_x *= wcross_sizefloat;
- wcross_size_y *= wcross_sizefloat;
-
- if(shottype == SHOTTYPE_HITENEMY || shottype == SHOTTYPE_HITWORLD)
- {
- drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x) + '0 0.5 0' * (vid_conheight - wcross_size_y), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
- }
- else
- {
- wcross_alpha *= 0.04 * 0.75;
- for(i = -2; i <= 2; ++i)
- for(j = -2; j <= 2; ++j)
- drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x + i) + '0 0.5 0' * (vid_conheight - wcross_size_y + j), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
- }
- }
- }
- }
-
- if(NextFrameCommand)
- {
- localcmd("\n", NextFrameCommand, "\n");
- NextFrameCommand = string_null;
- }
-}
-
-void Sbar_Draw();
-void CSQC_spider_HUD()
-{
- float rockets,reload,heat,hp,shield,i;
- vector p,pp;
-
- rockets = getstati(STAT_SPIDERBOT_ROCKETS);
- heat = min(getstatf(STAT_SPIDERBOT_HEAT),1);
- reload = min(getstatf(STAT_SPIDERBOT_RELOAD),1);
- hp = min(getstatf(STAT_SPIDERBOT_HEALTH),1);
- shield = min(getstatf(STAT_SPIDERBOT_SHIELD),1);
-
- // Draw health bar
- p = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
- p = p + '0 1 0' * vid_conheight - '0 32 0';
- //pp = ('0 1 0' * hp) + ('1 0 0' * (1-hp));
- drawfill(p, '256 0 0' * shield + '0 8 0' , '0.5 0.5 1', 0.75, DRAWFLAG_NORMAL);
- p_y += 8;
- drawfill(p, '256 0 0' * hp + '0 8 0' , '0 1 0', 0.75, DRAWFLAG_NORMAL);
- p_x += 256 * hp;
- drawfill(p, '256 0 0' * (1-hp) + '0 8 0' , '0 0 0', 0.75, DRAWFLAG_NORMAL);
-
- // Draw minigun heat indicator
- p = '0.5 0 0' * (vid_conwidth - 256);
- p = p + '0 1 0' * vid_conheight - '0 34 0';
- drawfill(p, '256 0 0' * (1-heat) + '0 2 0' ,'0 0 1', 0.5, DRAWFLAG_NORMAL);
- p_x += 256 * (1-heat);
- drawfill(p, '256 0 0' * heat + '0 2 0' , '1 0 0', 0.5, DRAWFLAG_NORMAL);
-
- // Draw rocket icons for loaded/empty tubes.
- pp = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
- pp += '0 1 0' * vid_conheight - '0 64 0';
- for(i = 0; i < 8; ++i)
- {
- p = pp + '1 0 0' * (rkt_size * i);
- if(rockets == 8)
- {
- if(floor(reload * 8) == i)
- {
- drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 0 0' + '0 1 0' * ((reload*8)-i), 0.75 , DRAWFLAG_NORMAL);
- }
- else if(i < reload * 8)
- drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 1 0', 0.75 , DRAWFLAG_NORMAL);
- else
- drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0.5 0.5 0.5', 0.75, DRAWFLAG_NORMAL);
- }
- else
- {
- if(i < rockets)
- drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 0 0', 0.25, DRAWFLAG_NORMAL);
- else
- drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 1 0' * reload, 0.75, DRAWFLAG_NORMAL);
- }
- }
-
- if (sb_showscores)
- {
- Sbar_DrawScoreboard();
- Sbar_DrawCenterPrint();
- }
-
-}
-void CSQC_common_hud(void)
-{
-
- // Sbar_SortFrags(); done in Sbar_Draw
- float hud;
- hud = getstati(STAT_HUD);
-
- //hud = 10;
- switch(hud)
- {
- case HUD_NORMAL:
- Sbar_Draw();
- break;
-
- case HUD_SPIDEBOT:
- CSQC_spider_HUD();
- break;
- }
-}
-
-
-// following vectors must be global to allow seamless switching between camera modes
-vector camera_offset, current_camera_offset, mouse_angles, current_angles, current_origin, current_position;
-void CSQC_Demo_Camera()
-{
- float speed, attenuation, dimensions;
- vector tmp, delta;
-
- if( cvar("camera_reset") || !camera_mode )
- {
- camera_offset = '0 0 0';
- current_angles = '0 0 0';
- camera_direction = '0 0 0';
- camera_offset_z += 30;
- camera_offset_x += 30 * -cos(current_angles_y * DEG2RAD);
- camera_offset_y += 30 * -sin(current_angles_y * DEG2RAD);
- current_origin = view_origin;
- current_camera_offset = camera_offset;
- cvar_set("camera_reset", "0");
- camera_mode = CAMERA_CHASE;
- }
-
- // Camera angles
- if( camera_roll )
- mouse_angles_z += camera_roll * cvar("camera_speed_roll");
-
- if(cvar("camera_look_player"))
- {
- local vector dir;
- local float n;
-
- dir = normalize(view_origin - current_position);
- n = mouse_angles_z;
- mouse_angles = vectoangles(dir);
- mouse_angles_x = mouse_angles_x * -1;
- mouse_angles_z = n;
- }
- else
- {
- tmp = getmousepos() * 0.1;
- if(vlen(tmp)>cvar("camera_mouse_treshold"))
- {
- mouse_angles_x += tmp_y * cos(mouse_angles_z * DEG2RAD) + (tmp_x * sin(mouse_angles_z * DEG2RAD));
- mouse_angles_y -= tmp_x * cos(mouse_angles_z * DEG2RAD) + (tmp_y * -sin(mouse_angles_z * DEG2RAD));
- }
- }
-
- while (mouse_angles_x < -180) mouse_angles_x = mouse_angles_x + 360;
- while (mouse_angles_x > 180) mouse_angles_x = mouse_angles_x - 360;
- while (mouse_angles_y < -180) mouse_angles_y = mouse_angles_y + 360;
- while (mouse_angles_y > 180) mouse_angles_y = mouse_angles_y - 360;
-
- // Fix difference when angles don't have the same sign
- delta = '0 0 0';
- if(mouse_angles_y < -60 && current_angles_y > 60)
- delta = '0 360 0';
- if(mouse_angles_y > 60 && current_angles_y < -60)
- delta = '0 -360 0';
-
- if(cvar("camera_look_player"))
- attenuation = cvar("camera_look_attenuation");
- else
- attenuation = cvar("camera_speed_attenuation");
-
- attenuation = 1 / max(1, attenuation);
- current_angles += (mouse_angles - current_angles + delta) * attenuation;
-
- while (current_angles_x < -180) current_angles_x = current_angles_x + 360;
- while (current_angles_x > 180) current_angles_x = current_angles_x - 360;
- while (current_angles_y < -180) current_angles_y = current_angles_y + 360;
- while (current_angles_y > 180) current_angles_y = current_angles_y - 360;
-
- // Camera position
- tmp = '0 0 0';
- dimensions = 0;
-
- if( camera_direction_x )
- {
- tmp_x = camera_direction_x * cos(current_angles_y * DEG2RAD);
- tmp_y = camera_direction_x * sin(current_angles_y * DEG2RAD);
- if( cvar("camera_forward_follows") && !cvar("camera_look_player") )
- tmp_z = camera_direction_x * -sin(current_angles_x * DEG2RAD);
- ++dimensions;
- }
-
- if( camera_direction_y )
- {
- tmp_x += camera_direction_y * -sin(current_angles_y * DEG2RAD);
- tmp_y += camera_direction_y * cos(current_angles_y * DEG2RAD) * cos(current_angles_z * DEG2RAD);
- tmp_z += camera_direction_y * sin(current_angles_z * DEG2RAD);
- ++dimensions;
- }
-
- if( camera_direction_z )
- {
- tmp_z += camera_direction_z * cos(current_angles_z * DEG2RAD);
- ++dimensions;
- }
-
- if(cvar("camera_free"))
- speed = cvar("camera_speed_free");
- else
- speed = cvar("camera_speed_chase");
-
- if(dimensions)
- {
- speed = speed * sqrt(1 / dimensions);
- camera_offset += tmp * speed;
- }
-
- current_camera_offset += (camera_offset - current_camera_offset) * attenuation;
-
- // Camera modes
- if( cvar("camera_free") )
- {
- if ( camera_mode == CAMERA_CHASE )
- {
- current_camera_offset = current_origin + current_camera_offset;
- camera_offset = current_origin + camera_offset;
- }
-
- camera_mode = CAMERA_FREE;
- current_position = current_camera_offset;
- }
- else
- {
- if ( camera_mode == CAMERA_FREE )
- {
- current_origin = view_origin;
- camera_offset = camera_offset - current_origin;
- current_camera_offset = current_camera_offset - current_origin;
- }
-
- camera_mode = CAMERA_CHASE;
-
- if(cvar("camera_chase_smoothly"))
- current_origin += (view_origin - current_origin) * attenuation;
- else
- current_origin = view_origin;
-
- current_position = current_origin + current_camera_offset;
- }
-
- R_SetView(VF_ANGLES, current_angles);
- R_SetView(VF_ORIGIN, current_position);
-}
+#define spider_rocket_icon "gfx/spiderbot/rocket_ico.tga"
+#define spider_rocket_targ "gfx/spiderbot/target.tga"
+#define SPIDER_CROSS "textures/spiderbot/cross.tga"
+#define rkt_size 32
+#define rld_size_x 256
+#define rld_size_y 16
+
+entity porto;
+vector polyline[16];
+float trace_dphitcontents;
+float trace_networkentity;
+float Q3SURFACEFLAG_SLICK = 2; // low friction surface
+float DPCONTENTS_SOLID = 1; // blocks player movement
+float DPCONTENTS_BODY = 32; // blocks player movement
+float DPCONTENTS_CORPSE = 64; // blocks player movement
+float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
+void Porto_Draw()
+{
+ vector p, dir, ang, q, nextdir;
+ float idx, portal_number, portal1_idx;
+
+ if(activeweapon != WEP_PORTO || spectatee_status || gametype == GAME_NEXBALL)
+ return;
+ if(intermission == 1)
+ return;
+ if(intermission == 2)
+ return;
+ if (getstati(STAT_HEALTH) <= 0)
+ return;
+
+ dir = view_forward;
+
+ if(angles_held_status)
+ {
+ makevectors(angles_held);
+ dir = v_forward;
+ }
+
+ p = view_origin;
+
+ polyline[0] = p;
+ idx = 1;
+ portal_number = 0;
+ nextdir = dir;
+
+ for(;;)
+ {
+ dir = nextdir;
+ traceline(p, p + 65536 * dir, TRUE, porto);
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+ return;
+ nextdir = dir - 2 * (dir * trace_plane_normal) * trace_plane_normal; // mirror dir at trace_plane_normal
+ p = trace_endpos;
+ polyline[idx] = p;
+ ++idx;
+ if(idx >= 16)
+ return;
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+ continue;
+ ++portal_number;
+ ang = vectoangles2(trace_plane_normal, dir);
+ ang_x = -ang_x;
+ makevectors(ang);
+ if(!CheckWireframeBox(porto, p - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ return;
+ if(portal_number == 1)
+ portal1_idx = idx;
+ if(portal_number >= 2)
+ break;
+ }
+
+ while(idx >= 2)
+ {
+ p = polyline[idx-2];
+ q = polyline[idx-1];
+ if(idx == 2)
+ p = p - view_up * 16;
+ if(idx-1 >= portal1_idx)
+ {
+ Draw_CylindricLine(p, q, 4, "", 1, 0, '0 0 1', 0.5, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ Draw_CylindricLine(p, q, 4, "", 1, 0, '1 0 0', 0.5, DRAWFLAG_NORMAL);
+ }
+ --idx;
+ }
+}
+
+/**
+ * Checks whether the server initiated a map restart (stat_game_starttime changed)
+ *
+ * TODO: Use a better solution where a common shared entitiy is used that contains
+ * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT
+ * and STAT_FRAGLIMIT to be auto-sent)
+ */
+void CheckForGamestartChange() {
+ float startTime;
+ startTime = getstatf(STAT_GAMESTARTTIME);
+ if (previous_game_starttime != startTime) {
+ if ((time + 5.0) < startTime) {
+ //if connecting to server while restart was active don't always play prepareforbattle
+ sound(self, CHAN_VOICE, "announcer/robotic/prepareforbattle.wav", VOL_BASEVOICE, ATTN_NONE);
+ }
+ if (time < startTime) {
+ restartAnnouncer = spawn();
+ restartAnnouncer.think = restartAnnouncer_Think;
+ restartAnnouncer.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime
+ }
+ }
+ previous_game_starttime = startTime;
+}
+
+void Porto_Init()
+{
+ porto = spawn();
+ porto.classname = "porto";
+ porto.draw = Porto_Draw;
+ porto.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+}
+
+float drawtime;
+
+float tan(float x)
+{
+ return sin(x) / cos(x);
+}
+float atan2(float y, float x)
+{
+ vector v;
+ v = '1 0 0' * x + '0 1 0' * y;
+ v = vectoangles(v);
+ return v_y * 0.01745329251994329576;
+}
+
+vector GetCurrentFov(float fov)
+{
+ float zoomsensitivity, zoomspeed, zoomfactor, zoomdir;
+
+ zoomsensitivity = cvar("cl_zoomsensitivity");
+ zoomfactor = cvar("cl_zoomfactor");
+ if(zoomfactor < 1 || zoomfactor > 16)
+ zoomfactor = 2.5;
+ zoomspeed = cvar("cl_zoomspeed");
+ if(zoomspeed >= 0)
+ if(zoomspeed < 0.5 || zoomspeed > 16)
+ zoomspeed = 3.5;
+
+ zoomdir = button_zoom;
+ if(getstati(STAT_ACTIVEWEAPON) == WEP_NEX) // do NOT use switchweapon here
+ zoomdir += button_attack2;
+ if(spectatee_status > 0 || isdemo())
+ {
+ if(spectatorbutton_zoom)
+ zoomdir = 0 + !zoomdir;
+ // do not even THINK about removing this 0
+ // _I_ know what I am doing
+ // fteqcc does not
+ }
+
+ if(zoomdir)
+ zoomin_effect = 0;
+
+ if(zoomin_effect || camera_active)
+ {
+ current_viewzoom = min(1, current_viewzoom + drawframetime);
+ }
+ else
+ {
+ if(zoomspeed < 0) // instant zoom
+ {
+ if(zoomdir)
+ current_viewzoom = 1 / zoomfactor;
+ else
+ current_viewzoom = 1;
+ }
+ else
+ {
+ if(zoomdir)
+ current_viewzoom = 1 / bound(1, 1 / current_viewzoom + drawframetime * zoomspeed * (zoomfactor - 1), zoomfactor);
+ else
+ current_viewzoom = bound(1 / zoomfactor, current_viewzoom + drawframetime * zoomspeed * (1 - 1 / zoomfactor), 1);
+ }
+ }
+
+ if(almost_equals(current_viewzoom, 1))
+ current_zoomfraction = 0;
+ else if(almost_equals(current_viewzoom, 1/zoomfactor))
+ current_zoomfraction = 1;
+ else
+ current_zoomfraction = (current_viewzoom - 1) / (1/zoomfactor - 1);
+
+ if(zoomsensitivity < 1)
+ setsensitivityscale(pow(current_viewzoom, 1 - zoomsensitivity));
+ else
+ setsensitivityscale(1);
+
+ float frustumx, frustumy, fovx, fovy;
+ frustumy = tan(fov * 0.00872664625997164788) * 0.75 * current_viewzoom;
+ frustumx = frustumy * vid_width / vid_height / vid_pixelheight;
+ fovx = atan2(frustumx, 1) / 0.00872664625997164788;
+ fovy = atan2(frustumy, 1) / 0.00872664625997164788;
+
+ return '1 0 0' * fovx + '0 1 0' * fovy;
+}
+
+// this function must match W_SetupShot!
+float zoomscript_caught;
+entity trueaim;
+
+#define SHOTTYPE_HITTEAM 1
+#define SHOTTYPE_HITOBSTRUCTION 2
+#define SHOTTYPE_HITWORLD 3
+#define SHOTTYPE_HITENEMY 4
+
+void TrueAim_Init()
+{
+ trueaim = spawn();
+ trueaim.classname = "trueaim";
+ trueaim.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+}
+
+float EnemyHitCheck(vector start, vector mi, vector ma, vector end)
+{
+ float t;
+ tracebox(start, mi, ma, end, MOVE_NORMAL, trueaim);
+ if(trace_networkentity < 1)
+ return SHOTTYPE_HITWORLD;
+ if(trace_networkentity > maxclients)
+ return SHOTTYPE_HITWORLD;
+ t = GetPlayerColor(trace_networkentity - 1);
+ if(teamplay)
+ if(t == myteam)
+ return SHOTTYPE_HITTEAM;
+ if(t == COLOR_SPECTATOR)
+ return SHOTTYPE_HITWORLD;
+ return SHOTTYPE_HITENEMY;
+}
+
+float TrueAimCheck()
+{
+ float nudge = 1; // added to traceline target and subtracted from result
+ vector vecs, trueaimpoint, w_shotorg;
+ vector mi, ma, dv;
+ float shottype;
+
+ mi = ma = '0 0 0';
+
+ switch(activeweapon)
+ {
+ case WEP_TUBA: // no aim
+ case WEP_PORTO: // shoots from eye
+ case WEP_HOOK: // no trueaim
+ case WEP_GRENADE_LAUNCHER: // toss curve
+ return SHOTTYPE_HITWORLD;
+ case WEP_CAMPINGRIFLE:
+ if(zoomscript_caught)
+ return EnemyHitCheck(view_origin, '0 0 0', '0 0 0', view_origin + view_forward * MAX_SHOT_DISTANCE);
+ break;
+ case WEP_ROCKET_LAUNCHER: // projectile has a size!
+ mi = '-3 -3 -3';
+ ma = '3 3 3';
+ break;
+ case WEP_SEEKER: // projectile has a size!
+ mi = '-2 -2 -2';
+ ma = '2 2 2';
+ break;
+ case WEP_ELECTRO: // projectile has a size!
+ mi = '0 0 -3';
+ ma = '0 0 -3';
+ break;
+ }
+
+ vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
+
+ traceline(view_origin, view_origin + view_forward * MAX_SHOT_DISTANCE, MOVE_NOMONSTERS, trueaim);
+ trueaimpoint = trace_endpos;
+
+ if(vecs_x > 0)
+ vecs_y = -vecs_y;
+ else
+ vecs = '0 0 0';
+
+ dv = view_right * vecs_y + view_up * vecs_z;
+ w_shotorg = view_origin + dv;
+
+ // now move the vecs forward as much as requested if possible
+ tracebox(w_shotorg, mi, ma, w_shotorg + view_forward * (vecs_x + nudge), MOVE_NORMAL, trueaim); // FIXME this MOVE_NORMAL part will misbehave a little in csqc
+ w_shotorg = trace_endpos - view_forward * nudge;
+
+ shottype = EnemyHitCheck(w_shotorg, mi, ma, trueaimpoint);
+ if(shottype != SHOTTYPE_HITWORLD)
+ return shottype;
+
+ // now test whether we will actually hit the trueaimpoint...
+ tracebox(w_shotorg, mi, ma, trueaimpoint, MOVE_NOMONSTERS, trueaim);
+
+ if(vlen(trace_endpos - trueaimpoint) > vlen(ma - mi) + 1)
+ // yes, this is an ugly hack... but it seems good enough to find out whether the test hits the same place as the initial trace
+ return SHOTTYPE_HITOBSTRUCTION;
+
+ return SHOTTYPE_HITWORLD;
+}
+
+void CSQC_common_hud(void);
+
+void CSQC_kh_hud(void);
+void CSQC_ctf_hud(void);
+void PostInit(void);
+void CSQC_Demo_Camera();
+float Sbar_WouldDrawScoreboard ();
+float view_set;
+float camera_mode;
+string NextFrameCommand;
+void CSQC_spider_HUD();
+void CSQC_UpdateView(float w, float h)
+{
+ entity e;
+ float fov;
+ float f, i, j;
+
+ dprint_load();
+ WaypointSprite_Load();
+
+ myteam = GetPlayerColor(player_localentnum - 1);
+
+ ticrate = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+
+ // Render the Scene
+ if(!intermission || !view_set)
+ {
+ view_origin = pmove_org + '0 0 1' * getstati(STAT_VIEWHEIGHT);
+ view_angles = input_angles;
+ makevectors(view_angles);
+ view_forward = v_forward;
+ view_right = v_right;
+ view_up = v_up;
+ view_set = 1;
+ }
+
+ vid_width = w;
+ vid_height = h;
+
+#ifdef BLURTEST
+ if(time > blurtest_time0 && time < blurtest_time1)
+ {
+ float r, t;
+
+ t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
+ r = t * blurtest_radius;
+ f = 1 / pow(t, blurtest_power) - 1;
+
+ cvar_set("r_glsl_postprocess", "1");
+ cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
+ }
+ else
+ {
+ cvar_set("r_glsl_postprocess", "0");
+ cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
+ }
+#endif
+
+ Fog_Force();
+
+ drawframetime = max(0.000001, time - drawtime);
+ drawtime = time;
+
+ // watch for gametype changes here...
+ // in ParseStuffCMD the cmd isn't executed yet :/
+ // might even be better to add the gametype to TE_CSQC_INIT...?
+ if(!postinit)
+ PostInit();
+
+ CheckForGamestartChange();
+ maptimeAnnouncer();
+
+ fov = cvar("fov");
+ if(button_zoom || fov <= 59.5)
+ {
+ if(!zoomscript_caught)
+ {
+ localcmd("+button4\n");
+ zoomscript_caught = 1;
+ ignore_plus_zoom += 1;
+ }
+ }
+ else
+ {
+ if(zoomscript_caught)
+ {
+ localcmd("-button4\n");
+ zoomscript_caught = 0;
+ ignore_minus_zoom += 1;
+ }
+ }
+
+ sbar_alpha_fg = cvar("sbar_alpha_fg" );
+ sbar_currentammo = cvar("sbar_showcurrentammo");
+ sbar_hudselector = cvar("sbar_hudselector");
+ sbar_hud_accuracy = cvar("sbar_hud_accuracy");
+ ColorTranslateMode = cvar("cl_stripcolorcodes");
+ activeweapon = getstati(STAT_SWITCHWEAPON);
+ f = cvar("teamplay");
+ if(f != teamplay)
+ {
+ teamplay = f;
+ Sbar_InitScores();
+ }
+
+ if(last_weapon != activeweapon) {
+ weapontime = time;
+ last_weapon = activeweapon;
+ }
+
+ // ALWAYS Clear Current Scene First
+ R_ClearScene();
+
+ // Assign Standard Viewflags
+ // Draw the World (and sky)
+ R_SetView(VF_DRAWWORLD, 1);
+
+ // Set the console size vars
+ vid_conwidth = cvar("vid_conwidth");
+ vid_conheight = cvar("vid_conheight");
+ vid_pixelheight = cvar("vid_pixelheight");
+
+ R_SetView(VF_FOV, GetCurrentFov(fov));
+
+ // Camera for demo playback
+ if(camera_active)
+ {
+ if(cvar("camera_enable"))
+ CSQC_Demo_Camera();
+ else
+ {
+ cvar_set("chase_active", ftos(chase_active_backup));
+ cvar_set("cl_demo_mousegrab", "0");
+ camera_active = FALSE;
+ }
+ }
+#ifdef CAMERATEST
+ else if(cvar("camera_enable"))
+#else
+ else if(cvar("camera_enable") && isdemo())
+#endif
+ {
+ // Enable required Darkplaces cvars
+ chase_active_backup = cvar("chase_active");
+ cvar_set("chase_active", "2");
+ cvar_set("cl_demo_mousegrab", "1");
+ camera_active = TRUE;
+ camera_mode = FALSE;
+ }
+
+ // Draw the Crosshair
+ float scoreboard_active;
+ scoreboard_active = Sbar_WouldDrawScoreboard();
+ R_SetView(VF_DRAWCROSSHAIR, 0); //Make sure engine crosshairs are always hidden
+
+ // Draw the Engine Status Bar (the default Quake HUD)
+ R_SetView(VF_DRAWENGINESBAR, 0);
+
+ // fetch this one only once per frame
+ sbar_showbinds = cvar("sbar_showbinds");
+ sbar_showbinds_limit = cvar("sbar_showbinds_limit");
+
+ // Update the mouse position
+ /*
+ mousepos_x = vid_conwidth;
+ mousepos_y = vid_conheight;
+ mousepos = mousepos*0.5 + getmousepos();
+ */
+
+ R_AddEntities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
+
+ e = self;
+ for(self = world; (self = nextent(self)); )
+ if(self.draw)
+ self.draw();
+ self = e;
+ R_RenderScene();
+
+ // now switch to 2D drawing mode by calling a 2D drawing function
+ // then polygon drawing will draw as 2D stuff, and NOT get queued until the
+ // next R_RenderScene call
+ drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0);
+
+ // Draw the mouse cursor
+ // NOTE: drawpic must happen after R_RenderScene for some reason
+ //drawpic(getmousepos(), "gfx/cursor.tga", '11 14 0', '1 1 1', 1, 0);
+ //drawstring('50 50', ftos(game), '10 10 0', '1 1 1', 1, 0);
+ //self = edict_num(player_localnum);
+ //drawstring('0 0', vtos(pmove_org), '8 8 0', '1 1 1', 1, 0);
+ //drawstring('0 8', strcat("ORG: ", vtos(self.origin), " state: ", ftos(self.ctf_state), " HP: ", ftos(self.health)), '8 8 0', '1 1 1', 1, 0);
+ // as long as the ctf part isn't in, this is useless
+ if(menu_visible)
+ menu_show();
+
+ /*if(gametype == GAME_CTF)
+ {
+ ctf_view();
+ } else */
+
+ // draw 2D entities
+ e = self;
+ for(self = world; (self = nextent(self)); )
+ if(self.draw2d)
+ self.draw2d();
+ self = e;
+
+ // draw radar
+ if(
+ ons_showmap
+ ||
+ (
+ !scoreboard_active
+ &&
+ cvar_string("cl_teamradar") != "0"
+ &&
+ (
+ cvar("cl_teamradar") == 2
+ ||
+ teamplay
+ )
+ )
+ )
+ teamradar_view();
+
+ if (cvar("cl_showpressedkeys")) // draw pressed keys when spectating and playing
+ {
+ if(spectatee_status > 0 || cvar("cl_showpressedkeys") >= 2)
+ Sbar_DrawPressedKeys();
+ }
+
+ if (cvar("cl_showspeed"))
+ Sbar_ShowSpeed();
+
+ // draw sbar
+ if(cvar("r_letterbox") == 0)
+ Sbar_DrawCenterPrint(); // draw centerprint messages even if viewsize >= 120
+
+ float hud;
+ hud = getstati(STAT_HUD);
+ if(hud == HUD_SPIDEBOT)
+ {
+ vector sz;
+ CSQC_spider_HUD();
+ sz = drawgetimagesize(SPIDER_CROSS);
+ sz_x *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
+ sz_y *= cvar_or("cl_vehicle_spiderbot_cross_size",1);
+ drawpic('0.5 0 0' * (vid_conwidth - sz_x) + '0 0.5 0' * (vid_conheight - sz_y), SPIDER_CROSS, sz, '1 1 1', cvar_or("cl_vehicle_spiderbot_cross_alpha",0.6), DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ if(cvar("r_letterbox") == 0)
+ if(cvar("viewsize") < 120)
+ CSQC_common_hud();
+
+ // crosshair goes VERY LAST
+ if(!scoreboard_active && !ons_showmap && !camera_active) {
+ // TrueAim check
+ float shottype;
+
+ if(cvar("crosshair_hittest"))
+ shottype = TrueAimCheck();
+ else
+ shottype = SHOTTYPE_HITWORLD;
+
+ string wcross_style;
+ wcross_style = cvar_string("crosshair");
+
+ if (wcross_style != "0") {
+ vector wcross_color, wcross_size;
+ string wcross_wep, wcross_name;
+ float wcross_alpha, wcross_sizefloat;
+
+ wcross_color_x = cvar("crosshair_color_red");
+ wcross_color_y = cvar("crosshair_color_green");
+ wcross_color_z = cvar("crosshair_color_blue");
+ wcross_alpha = cvar("crosshair_color_alpha");
+ wcross_sizefloat = cvar("crosshair_size");
+ if (cvar("crosshair_per_weapon")) {
+ e = get_weaponinfo(activeweapon);
+ if (e && e.netname != "")
+ {
+ wcross_wep = e.netname;
+ wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
+ if(wcross_style == "")
+ wcross_style = e.netname;
+
+ if(!cvar("crosshair_color_override"))
+ {
+ wcross_color_x = cvar(strcat("crosshair_", wcross_wep, "_color_red"));
+ wcross_color_y = cvar(strcat("crosshair_", wcross_wep, "_color_green"));
+ wcross_color_z = cvar(strcat("crosshair_", wcross_wep, "_color_blue"));
+ }
+
+ wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_color_alpha"));
+ wcross_sizefloat *= cvar(strcat("crosshair_", wcross_wep, "_size"));
+ }
+ }
+
+ wcross_name = strcat("gfx/crosshair", wcross_style);
+
+ if(shottype == SHOTTYPE_HITENEMY)
+ wcross_sizefloat *= cvar("crosshair_hittest"); // is not queried if hittest is 0
+ if(shottype == SHOTTYPE_HITTEAM)
+ wcross_sizefloat /= cvar("crosshair_hittest"); // is not queried if hittest is 0
+
+ wcross_size = drawgetimagesize(wcross_name);
+ wcross_size_x *= wcross_sizefloat;
+ wcross_size_y *= wcross_sizefloat;
+
+ if(shottype == SHOTTYPE_HITENEMY || shottype == SHOTTYPE_HITWORLD)
+ {
+ drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x) + '0 0.5 0' * (vid_conheight - wcross_size_y), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ wcross_alpha *= 0.04 * 0.75;
+ for(i = -2; i <= 2; ++i)
+ for(j = -2; j <= 2; ++j)
+ drawpic('0.5 0 0' * (vid_conwidth - wcross_size_x + i) + '0 0.5 0' * (vid_conheight - wcross_size_y + j), wcross_name, wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL);
+ }
+ }
+ }
+ }
+
+ if(NextFrameCommand)
+ {
+ localcmd("\n", NextFrameCommand, "\n");
+ NextFrameCommand = string_null;
+ }
+}
+
+void Sbar_Draw();
+void CSQC_spider_HUD()
+{
+ float rockets,reload,heat,hp,shield,i;
+ vector p,pp;
+
+ rockets = getstati(STAT_SPIDERBOT_ROCKETS);
+ heat = min(getstatf(STAT_SPIDERBOT_HEAT),1);
+ reload = min(getstatf(STAT_SPIDERBOT_RELOAD),1);
+ hp = min(getstatf(STAT_SPIDERBOT_HEALTH),1);
+ shield = min(getstatf(STAT_SPIDERBOT_SHIELD),1);
+
+ // Draw health bar
+ p = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
+ p = p + '0 1 0' * vid_conheight - '0 32 0';
+ //pp = ('0 1 0' * hp) + ('1 0 0' * (1-hp));
+ drawfill(p, '256 0 0' * shield + '0 8 0' , '0.5 0.5 1', 0.75, DRAWFLAG_NORMAL);
+ p_y += 8;
+ drawfill(p, '256 0 0' * hp + '0 8 0' , '0 1 0', 0.75, DRAWFLAG_NORMAL);
+ p_x += 256 * hp;
+ drawfill(p, '256 0 0' * (1-hp) + '0 8 0' , '0 0 0', 0.75, DRAWFLAG_NORMAL);
+
+ // Draw minigun heat indicator
+ p = '0.5 0 0' * (vid_conwidth - 256);
+ p = p + '0 1 0' * vid_conheight - '0 34 0';
+ drawfill(p, '256 0 0' * (1-heat) + '0 2 0' ,'0 0 1', 0.5, DRAWFLAG_NORMAL);
+ p_x += 256 * (1-heat);
+ drawfill(p, '256 0 0' * heat + '0 2 0' , '1 0 0', 0.5, DRAWFLAG_NORMAL);
+
+ // Draw rocket icons for loaded/empty tubes.
+ pp = '0.5 0 0' * (vid_conwidth - (rkt_size * 8));
+ pp += '0 1 0' * vid_conheight - '0 64 0';
+ for(i = 0; i < 8; ++i)
+ {
+ p = pp + '1 0 0' * (rkt_size * i);
+ if(rockets == 8)
+ {
+ if(floor(reload * 8) == i)
+ {
+ drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 0 0' + '0 1 0' * ((reload*8)-i), 0.75 , DRAWFLAG_NORMAL);
+ }
+ else if(i < reload * 8)
+ drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '1 1 0', 0.75 , DRAWFLAG_NORMAL);
+ else
+ drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0.5 0.5 0.5', 0.75, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ if(i < rockets)
+ drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 0 0', 0.25, DRAWFLAG_NORMAL);
+ else
+ drawpic(p, spider_rocket_icon, '1 1 0' * rkt_size, '0 1 0' * reload, 0.75, DRAWFLAG_NORMAL);
+ }
+ }
+
+ if (sb_showscores)
+ {
+ Sbar_DrawScoreboard();
+ Sbar_DrawCenterPrint();
+ }
+
+}
+void CSQC_common_hud(void)
+{
+
+ // Sbar_SortFrags(); done in Sbar_Draw
+ float hud;
+ hud = getstati(STAT_HUD);
+
+ //hud = 10;
+ switch(hud)
+ {
+ case HUD_NORMAL:
+ Sbar_Draw();
+ break;
+
+ case HUD_SPIDEBOT:
+ CSQC_spider_HUD();
+ break;
+ }
+}
+
+
+// following vectors must be global to allow seamless switching between camera modes
+vector camera_offset, current_camera_offset, mouse_angles, current_angles, current_origin, current_position;
+void CSQC_Demo_Camera()
+{
+ float speed, attenuation, dimensions;
+ vector tmp, delta;
+
+ if( cvar("camera_reset") || !camera_mode )
+ {
+ camera_offset = '0 0 0';
+ current_angles = '0 0 0';
+ camera_direction = '0 0 0';
+ camera_offset_z += 30;
+ camera_offset_x += 30 * -cos(current_angles_y * DEG2RAD);
+ camera_offset_y += 30 * -sin(current_angles_y * DEG2RAD);
+ current_origin = view_origin;
+ current_camera_offset = camera_offset;
+ cvar_set("camera_reset", "0");
+ camera_mode = CAMERA_CHASE;
+ }
+
+ // Camera angles
+ if( camera_roll )
+ mouse_angles_z += camera_roll * cvar("camera_speed_roll");
+
+ if(cvar("camera_look_player"))
+ {
+ local vector dir;
+ local float n;
+
+ dir = normalize(view_origin - current_position);
+ n = mouse_angles_z;
+ mouse_angles = vectoangles(dir);
+ mouse_angles_x = mouse_angles_x * -1;
+ mouse_angles_z = n;
+ }
+ else
+ {
+ tmp = getmousepos() * 0.1;
+ if(vlen(tmp)>cvar("camera_mouse_treshold"))
+ {
+ mouse_angles_x += tmp_y * cos(mouse_angles_z * DEG2RAD) + (tmp_x * sin(mouse_angles_z * DEG2RAD));
+ mouse_angles_y -= tmp_x * cos(mouse_angles_z * DEG2RAD) + (tmp_y * -sin(mouse_angles_z * DEG2RAD));
+ }
+ }
+
+ while (mouse_angles_x < -180) mouse_angles_x = mouse_angles_x + 360;
+ while (mouse_angles_x > 180) mouse_angles_x = mouse_angles_x - 360;
+ while (mouse_angles_y < -180) mouse_angles_y = mouse_angles_y + 360;
+ while (mouse_angles_y > 180) mouse_angles_y = mouse_angles_y - 360;
+
+ // Fix difference when angles don't have the same sign
+ delta = '0 0 0';
+ if(mouse_angles_y < -60 && current_angles_y > 60)
+ delta = '0 360 0';
+ if(mouse_angles_y > 60 && current_angles_y < -60)
+ delta = '0 -360 0';
+
+ if(cvar("camera_look_player"))
+ attenuation = cvar("camera_look_attenuation");
+ else
+ attenuation = cvar("camera_speed_attenuation");
+
+ attenuation = 1 / max(1, attenuation);
+ current_angles += (mouse_angles - current_angles + delta) * attenuation;
+
+ while (current_angles_x < -180) current_angles_x = current_angles_x + 360;
+ while (current_angles_x > 180) current_angles_x = current_angles_x - 360;
+ while (current_angles_y < -180) current_angles_y = current_angles_y + 360;
+ while (current_angles_y > 180) current_angles_y = current_angles_y - 360;
+
+ // Camera position
+ tmp = '0 0 0';
+ dimensions = 0;
+
+ if( camera_direction_x )
+ {
+ tmp_x = camera_direction_x * cos(current_angles_y * DEG2RAD);
+ tmp_y = camera_direction_x * sin(current_angles_y * DEG2RAD);
+ if( cvar("camera_forward_follows") && !cvar("camera_look_player") )
+ tmp_z = camera_direction_x * -sin(current_angles_x * DEG2RAD);
+ ++dimensions;
+ }
+
+ if( camera_direction_y )
+ {
+ tmp_x += camera_direction_y * -sin(current_angles_y * DEG2RAD);
+ tmp_y += camera_direction_y * cos(current_angles_y * DEG2RAD) * cos(current_angles_z * DEG2RAD);
+ tmp_z += camera_direction_y * sin(current_angles_z * DEG2RAD);
+ ++dimensions;
+ }
+
+ if( camera_direction_z )
+ {
+ tmp_z += camera_direction_z * cos(current_angles_z * DEG2RAD);
+ ++dimensions;
+ }
+
+ if(cvar("camera_free"))
+ speed = cvar("camera_speed_free");
+ else
+ speed = cvar("camera_speed_chase");
+
+ if(dimensions)
+ {
+ speed = speed * sqrt(1 / dimensions);
+ camera_offset += tmp * speed;
+ }
+
+ current_camera_offset += (camera_offset - current_camera_offset) * attenuation;
+
+ // Camera modes
+ if( cvar("camera_free") )
+ {
+ if ( camera_mode == CAMERA_CHASE )
+ {
+ current_camera_offset = current_origin + current_camera_offset;
+ camera_offset = current_origin + camera_offset;
+ }
+
+ camera_mode = CAMERA_FREE;
+ current_position = current_camera_offset;
+ }
+ else
+ {
+ if ( camera_mode == CAMERA_FREE )
+ {
+ current_origin = view_origin;
+ camera_offset = camera_offset - current_origin;
+ current_camera_offset = current_camera_offset - current_origin;
+ }
+
+ camera_mode = CAMERA_CHASE;
+
+ if(cvar("camera_chase_smoothly"))
+ current_origin += (view_origin - current_origin) * attenuation;
+ else
+ current_origin = view_origin;
+
+ current_position = current_origin + current_camera_offset;
+ }
+
+ R_SetView(VF_ANGLES, current_angles);
+ R_SetView(VF_ORIGIN, current_position);
+}
Property changes on: trunk/data/qcsrc/client/View.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/bgmscript.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/bgmscript.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/casings.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/csqc_builtins.qc
===================================================================
--- trunk/data/qcsrc/client/csqc_builtins.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/csqc_builtins.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,287 +1,287 @@
-void (vector ang) makevectors = #1;
-void(entity e, vector o) setorigin = #2;
-void (entity e, string m) setmodel = #3;
-void(entity e, vector min, vector max) setsize = #4;
-
-void () break = #6;
-float () random = #7;
-void (entity e, float chan, string samp, float vol, float atten) sound = #8;
-vector (vector v) normalize = #9;
-void (string e) error = #10;
-void (string e) objerror = #11;
-float (vector v) vlen = #12;
-float (vector v) vectoyaw = #13;
-entity () spawn = #14;
-void (entity e) remove = #15;
-
-void (vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
-
-entity (entity start, .string fld, string match) find = #18;
-string (string s) precache_sound = #19;
-string (string s) precache_model = #20;
-
-//void (string s) dprint = #25;
-string (float f) ftos = #26;
-string (vector v) vtos = #27;
-void () coredump = #28;
-void () traceon = #29;
-void () traceoff = #30;
-void (entity e) eprint = #31;
-
-float (float v) rint = #36;
-float (float v) floor = #37;
-float (float v) ceil = #38;
-
-float (vector v) pointcontents = #41;
-float (float f) fabs = #43;
-
-float (string s) cvar = #45;
-void (string s, ...) localcmd = #46;
-entity (entity e) nextent = #47;
-
-vector (vector v) vectoangles = #51;
-vector (vector v, vector w) vectoangles2 = #51;
-
-void (string var, string val) cvar_set = #72;
-
-
-float() ReadByte = #360;
-float() ReadChar = #361;
-float() ReadShort = #362;
-float() ReadLong = #363;
-float() ReadCoord = #364;
-float() ReadAngle = #365;
-string() ReadString = #366; //warning: this returns a temporary!
-
-float(string s) stof = #81;
-
-
-void (vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
-float (string name, string value, ...) registercvar = #93;
-
-entity (entity start, .entity fld, entity match) findentity = #98;
-entity (entity start, .float fld, float match) findfloat = #98;
-
-float (string s) checkextension = #99;
-
-float (string filename, float mode) fopen = #110;
-void (float fhandle) fclose = #111;
-string (float fhandle) fgets = #112;
-void (float fhandle, string s) fputs = #113;
-float (string s) strlen = #114;
-string (...) strcat = #115;
-string (string s, float start, float length) substring = #116;
-vector (string s) stov = #117;
-string (string s) strzone = #118;
-void (string s) strunzone = #119;
-
-void () R_ClearScene = #300;
-void (float mask) R_AddEntities = #301;
-void (entity e) R_AddEntity = #302;
-float (float property, ...) R_SetView = #303;
-void () R_RenderScene = #304;
-void (vector org, float radius, vector rgb) R_AddDynamicLight = #305;
-void () R_CalcRefDef = #306;
-
-vector (vector v) cs_unproject = #310;
-vector (vector v) cs_project = #311;
-
-void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags) = #315;
-float iscachedpic(string name) = #316;
-string precache_pic(string name, ...) = #317;
-vector drawgetimagesize(string pic) = #318;
-void freepic(string name) = #319;
-float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #320;
-float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #321;
-float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #322;
-float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #323;
-void drawsetcliparea(float x, float y, float width, float height) = #324;
-void drawresetcliparea(void) = #325;
-float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #326;
-float stringwidth(string text, float handleColors) = #327;
-float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328;
-
-
-float (float statnum) getstatf = #330;
-float (float statnum) getstati = #331;
-string (float statnum) getstats = #332;
-
-void (entity e, float i) setmodelindex = #333;
-string (float i) modelnameforindex = #334;
-
-float(string efname) particleeffectnum = #335;
-void(entity ent, float effectnum, vector start, vector end, ...) trailparticles = #336;
-void (float efnum, vector org, vector vel, float countmultiplier, ...) pointparticles = #337;
-
-void (string s, ...) cprint = #338;
-void (string s, ...) print = #339;
-
-void (float scale) setsensitivityscale = #346;
-
-
-void (float framenum) RetrieveMovementFrame = #345;
-void () DefaultPlayerPhysics = #347;
-
-string (float playernum, string key) getplayerkey = #348;
-void (string cmdname) registercmd = #352;
-vector () getmousepos = #344;
-
-string (string s) uncolorstring = #170;
-
-void (vector org, vector forward, vector right, vector up) setlistener = #351;
-
-float (vector start, vector end, float ignore, float csqcents) selecttraceline = #355;
-float () isdemo = #349;
-float () isserver = #350;
-
-void (float f) setwantsmousemove = #343;
-string (float key) getkeybind = #342;
-//string (float f) chr = #78;
-string (float f) chr = #78;
-float(string str, float ofs) str2chr = #222;
-string(float c, ...) chr2str = #223;
-
-vector (vector org) getlight = #92;
-
-entity (.string fld, string match) findchain = #402;
-entity (.float fld, float match) findchainflags = #450;
-entity (.entity fld, entity match) findchainentity = #403;
-entity (.float fld, float match) findchainfloat = #403;
-entity (entity start, .float fld, float match) findflags = #449;
-
-float (string pattern, float caseinsensitive, float quiet) search_begin = #444;
-void (float handle) search_end = #445;
-float (float handle) search_getsize = #446;
-string (float handle, float num) search_getfilename = #447;
-
-
-float (entity e, float s) getsurfacenumpoints = #434;
-vector (entity e, float s, float n) getsurfacepoint = #435;
-vector (entity e, float s) getsurfacenormal = #436;
-string (entity e, float s) getsurfacetexture = #437;
-float (entity e, vector p) getsurfacenearpoint = #438;
-vector (entity e, float s, vector p) getsurfaceclippedpoint = #439;
-
-float (float a, float b) min = #94;
-float (float a, float b, float c) min3 = #94;
-float (float a, float b, float c, float d) min4 = #94;
-float (float a, float b, float c, float d, float e) min5 = #94;
-float (float a, float b, float c, float d, float e, float f) min6 = #94;
-float (float a, float b, float c, float d, float e, float f, float g) min7 = #94;
-float (float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94;
-float (float a, float b) max = #95;
-float (float a, float b, float c) max3 = #95;
-float (float a, float b, float c, float d) max4 = #95;
-float (float a, float b, float c, float d, float e) max5 = #95;
-float (float a, float b, float c, float d, float e, float f) max6 = #95;
-float (float a, float b, float c, float d, float e, float f, float g) max7 = #95;
-float (float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95;
-float (float minimum, float val, float maximum) bound = #96;
-
-vector () randomvec = #91;
-
-float (float val) sin = #60;
-float (float val) cos = #61;
-float (float val) sqrt = #62;
-float (float a, float b) pow = #97;
-
-void (vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
-
-void (vector org, vector velocity, float howmany) te_blood = #405;
-void (vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
-void (vector org, float radius, float lifetime, vector color) te_customflash = #417;
-void(vector org, vector color) te_explosionrgb = #407;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
-void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
-void(vector org) te_plasmaburn = #433;
-void(vector org) te_gunshotquad = #412;
-void(vector org) te_spikequad = #413;
-void(vector org) te_superspikequad = #414;
-void(vector org) te_explosionquad = #415;
-void(vector org) te_smallflash = #416;
-void(vector org, vector vel, float howmany) te_spark = #411;
-
-void(vector org) te_gunshot = #418;
-void(vector org) te_spike = #419;
-void(vector org) te_superspike = #420;
-void(vector org) te_explosion = #421;
-void(vector org) te_tarexplosion = #422;
-void(vector org) te_wizspike = #423;
-void(vector org) te_knightspike = #424;
-void(vector org) te_lavasplash = #425;
-void(vector org) te_teleport = #426;
-void(vector org, float color, float colorlength) te_explosion2 = #427;
-void(entity own, vector start, vector end) te_lightning1 = #428;
-void(entity own, vector start, vector end) te_lightning2 = #429;
-void(entity own, vector start, vector end) te_lightning3 = #430;
-void(entity own, vector start, vector end) te_beam = #431;
-
-float (entity ent, string tagname) gettagindex = #451;
-vector (entity ent, float tagindex) gettaginfo = #452;
-
-float (string s) tokenize = #441;
-string (float argnum) argv = #442;
-
-string (string s) cvar_string = #448;
-
-float () buf_create = #460;
-void (float bufhandle) buf_del = #461;
-float (float bufhandle) buf_getsize = #462;
-void (float bufhandle_from, float bufhandle_to) buf_copy = #463;
-void (float bufhandle, float sortpower, float backward) buf_sort = #464;
-string (float bufhandle, string glue) buf_implode = #465;
-string (float bufhandle, float string_index) bufstr_get = #466;
-void (float bufhandle, float string_index, string str) bufstr_set = #467;
-float (float bufhandle, string str, float order) bufstr_add = #468;
-void (float bufhandle, float string_index) bufstr_free = #469;
-
-float () onground = #355;
-
-void(string texturename, ...) R_BeginPolygon = #306;
-void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307;
-void() R_EndPolygon = #308;
-
-float(string s, float num) charindex = #356;
-
-// Darkplaces Additional Functions
-string(string s) strdecolorize = #477;
-string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
-string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
-float(string s) strlennocol = #476;
-
-void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
-
-// added by blub
-
-string(string key) serverkey = #354;
-float(string s1, string s2) strcasecmp = #229;
-float(string s1, string s2, float len) strncasecmp = #230;
-float(string str, string sub, float startoffs) strstrofs = #221;
-//float(string str, string sub) strstrofs = #221;
-entity(float num) edict_num = #459;
-string(void) ReadPicture = #501;
-string(string filename) whichpack = #503;
-float(entity ent) num_for_edict = #512;
-float(string s, string separator1, ...) tokenizebyseparator = #479;
-string(string in) uri_unescape = #511;
-float(float caseinsensitive, string s, ...) crc16 = #494;
-string(string info, string key) infoget = #227;
-string(string info, string key, string value, ...) infoadd = #226;
-string(string in) uri_escape = #510;
-
-string keynumtostring(float keynum) = #520;
-string findkeysforcommand(string command) = #521;
-
-string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
-float(entity ent) wasfreed = #353;
-
-entity(vector org, float rad) findradius = #22;
-
-string(float uselocaltime, string format, ...) strftime = #478;
-float(float timer) gettime = #519;
-#define GETTIME_CDTRACK 4
-
-float(string s) tokenize_console = #514;
-float(float i) argv_start_index = #515;
-float(float i) argv_end_index = #516;
+void (vector ang) makevectors = #1;
+void(entity e, vector o) setorigin = #2;
+void (entity e, string m) setmodel = #3;
+void(entity e, vector min, vector max) setsize = #4;
+
+void () break = #6;
+float () random = #7;
+void (entity e, float chan, string samp, float vol, float atten) sound = #8;
+vector (vector v) normalize = #9;
+void (string e) error = #10;
+void (string e) objerror = #11;
+float (vector v) vlen = #12;
+float (vector v) vectoyaw = #13;
+entity () spawn = #14;
+void (entity e) remove = #15;
+
+void (vector v1, vector v2, float nomonsters, entity forent) traceline = #16;
+
+entity (entity start, .string fld, string match) find = #18;
+string (string s) precache_sound = #19;
+string (string s) precache_model = #20;
+
+//void (string s) dprint = #25;
+string (float f) ftos = #26;
+string (vector v) vtos = #27;
+void () coredump = #28;
+void () traceon = #29;
+void () traceoff = #30;
+void (entity e) eprint = #31;
+
+float (float v) rint = #36;
+float (float v) floor = #37;
+float (float v) ceil = #38;
+
+float (vector v) pointcontents = #41;
+float (float f) fabs = #43;
+
+float (string s) cvar = #45;
+void (string s, ...) localcmd = #46;
+entity (entity e) nextent = #47;
+
+vector (vector v) vectoangles = #51;
+vector (vector v, vector w) vectoangles2 = #51;
+
+void (string var, string val) cvar_set = #72;
+
+
+float() ReadByte = #360;
+float() ReadChar = #361;
+float() ReadShort = #362;
+float() ReadLong = #363;
+float() ReadCoord = #364;
+float() ReadAngle = #365;
+string() ReadString = #366; //warning: this returns a temporary!
+
+float(string s) stof = #81;
+
+
+void (vector v1, vector min, vector max, vector v2, float nomonsters, entity forent) tracebox = #90;
+float (string name, string value, ...) registercvar = #93;
+
+entity (entity start, .entity fld, entity match) findentity = #98;
+entity (entity start, .float fld, float match) findfloat = #98;
+
+float (string s) checkextension = #99;
+
+float (string filename, float mode) fopen = #110;
+void (float fhandle) fclose = #111;
+string (float fhandle) fgets = #112;
+void (float fhandle, string s) fputs = #113;
+float (string s) strlen = #114;
+string (...) strcat = #115;
+string (string s, float start, float length) substring = #116;
+vector (string s) stov = #117;
+string (string s) strzone = #118;
+void (string s) strunzone = #119;
+
+void () R_ClearScene = #300;
+void (float mask) R_AddEntities = #301;
+void (entity e) R_AddEntity = #302;
+float (float property, ...) R_SetView = #303;
+void () R_RenderScene = #304;
+void (vector org, float radius, vector rgb) R_AddDynamicLight = #305;
+void () R_CalcRefDef = #306;
+
+vector (vector v) cs_unproject = #310;
+vector (vector v) cs_project = #311;
+
+void drawline(float width, vector pos1, vector pos2, vector rgb, float alpha, float flags) = #315;
+float iscachedpic(string name) = #316;
+string precache_pic(string name, ...) = #317;
+vector drawgetimagesize(string pic) = #318;
+void freepic(string name) = #319;
+float drawcharacter(vector position, float character, vector scale, vector rgb, float alpha, float flag) = #320;
+float drawstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) = #321;
+float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #322;
+float drawfill(vector position, vector size, vector rgb, float alpha, float flag) = #323;
+void drawsetcliparea(float x, float y, float width, float height) = #324;
+void drawresetcliparea(void) = #325;
+float drawcolorcodedstring(vector position, string text, vector scale, float alpha, float flag) = #326;
+float stringwidth(string text, float handleColors) = #327;
+float drawsubpic(vector position, vector size, string pic, vector srcPosition, vector srcSize, vector rgb, float alpha, float flag) = #328;
+
+
+float (float statnum) getstatf = #330;
+float (float statnum) getstati = #331;
+string (float statnum) getstats = #332;
+
+void (entity e, float i) setmodelindex = #333;
+string (float i) modelnameforindex = #334;
+
+float(string efname) particleeffectnum = #335;
+void(entity ent, float effectnum, vector start, vector end, ...) trailparticles = #336;
+void (float efnum, vector org, vector vel, float countmultiplier, ...) pointparticles = #337;
+
+void (string s, ...) cprint = #338;
+void (string s, ...) print = #339;
+
+void (float scale) setsensitivityscale = #346;
+
+
+void (float framenum) RetrieveMovementFrame = #345;
+void () DefaultPlayerPhysics = #347;
+
+string (float playernum, string key) getplayerkey = #348;
+void (string cmdname) registercmd = #352;
+vector () getmousepos = #344;
+
+string (string s) uncolorstring = #170;
+
+void (vector org, vector forward, vector right, vector up) setlistener = #351;
+
+float (vector start, vector end, float ignore, float csqcents) selecttraceline = #355;
+float () isdemo = #349;
+float () isserver = #350;
+
+void (float f) setwantsmousemove = #343;
+string (float key) getkeybind = #342;
+//string (float f) chr = #78;
+string (float f) chr = #78;
+float(string str, float ofs) str2chr = #222;
+string(float c, ...) chr2str = #223;
+
+vector (vector org) getlight = #92;
+
+entity (.string fld, string match) findchain = #402;
+entity (.float fld, float match) findchainflags = #450;
+entity (.entity fld, entity match) findchainentity = #403;
+entity (.float fld, float match) findchainfloat = #403;
+entity (entity start, .float fld, float match) findflags = #449;
+
+float (string pattern, float caseinsensitive, float quiet) search_begin = #444;
+void (float handle) search_end = #445;
+float (float handle) search_getsize = #446;
+string (float handle, float num) search_getfilename = #447;
+
+
+float (entity e, float s) getsurfacenumpoints = #434;
+vector (entity e, float s, float n) getsurfacepoint = #435;
+vector (entity e, float s) getsurfacenormal = #436;
+string (entity e, float s) getsurfacetexture = #437;
+float (entity e, vector p) getsurfacenearpoint = #438;
+vector (entity e, float s, vector p) getsurfaceclippedpoint = #439;
+
+float (float a, float b) min = #94;
+float (float a, float b, float c) min3 = #94;
+float (float a, float b, float c, float d) min4 = #94;
+float (float a, float b, float c, float d, float e) min5 = #94;
+float (float a, float b, float c, float d, float e, float f) min6 = #94;
+float (float a, float b, float c, float d, float e, float f, float g) min7 = #94;
+float (float a, float b, float c, float d, float e, float f, float g, float h) min8 = #94;
+float (float a, float b) max = #95;
+float (float a, float b, float c) max3 = #95;
+float (float a, float b, float c, float d) max4 = #95;
+float (float a, float b, float c, float d, float e) max5 = #95;
+float (float a, float b, float c, float d, float e, float f) max6 = #95;
+float (float a, float b, float c, float d, float e, float f, float g) max7 = #95;
+float (float a, float b, float c, float d, float e, float f, float g, float h) max8 = #95;
+float (float minimum, float val, float maximum) bound = #96;
+
+vector () randomvec = #91;
+
+float (float val) sin = #60;
+float (float val) cos = #61;
+float (float val) sqrt = #62;
+float (float a, float b) pow = #97;
+
+void (vector org, string modelname, float startframe, float endframe, float framerate) effect = #404;
+
+void (vector org, vector velocity, float howmany) te_blood = #405;
+void (vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower = #406;
+void (vector org, float radius, float lifetime, vector color) te_customflash = #417;
+void(vector org, vector color) te_explosionrgb = #407;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube = #408;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain = #409;
+void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow = #410;
+void(vector org) te_plasmaburn = #433;
+void(vector org) te_gunshotquad = #412;
+void(vector org) te_spikequad = #413;
+void(vector org) te_superspikequad = #414;
+void(vector org) te_explosionquad = #415;
+void(vector org) te_smallflash = #416;
+void(vector org, vector vel, float howmany) te_spark = #411;
+
+void(vector org) te_gunshot = #418;
+void(vector org) te_spike = #419;
+void(vector org) te_superspike = #420;
+void(vector org) te_explosion = #421;
+void(vector org) te_tarexplosion = #422;
+void(vector org) te_wizspike = #423;
+void(vector org) te_knightspike = #424;
+void(vector org) te_lavasplash = #425;
+void(vector org) te_teleport = #426;
+void(vector org, float color, float colorlength) te_explosion2 = #427;
+void(entity own, vector start, vector end) te_lightning1 = #428;
+void(entity own, vector start, vector end) te_lightning2 = #429;
+void(entity own, vector start, vector end) te_lightning3 = #430;
+void(entity own, vector start, vector end) te_beam = #431;
+
+float (entity ent, string tagname) gettagindex = #451;
+vector (entity ent, float tagindex) gettaginfo = #452;
+
+float (string s) tokenize = #441;
+string (float argnum) argv = #442;
+
+string (string s) cvar_string = #448;
+
+float () buf_create = #460;
+void (float bufhandle) buf_del = #461;
+float (float bufhandle) buf_getsize = #462;
+void (float bufhandle_from, float bufhandle_to) buf_copy = #463;
+void (float bufhandle, float sortpower, float backward) buf_sort = #464;
+string (float bufhandle, string glue) buf_implode = #465;
+string (float bufhandle, float string_index) bufstr_get = #466;
+void (float bufhandle, float string_index, string str) bufstr_set = #467;
+float (float bufhandle, string str, float order) bufstr_add = #468;
+void (float bufhandle, float string_index) bufstr_free = #469;
+
+float () onground = #355;
+
+void(string texturename, ...) R_BeginPolygon = #306;
+void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex = #307;
+void() R_EndPolygon = #308;
+
+float(string s, float num) charindex = #356;
+
+// Darkplaces Additional Functions
+string(string s) strdecolorize = #477;
+string(string s) strtolower = #480; // returns the passed in string in pure lowercase form
+string(string s) strtoupper = #481; // returns the passed in string in pure uppercase form
+float(string s) strlennocol = #476;
+
+void(vector origin, string sample, float volume, float attenuation) pointsound = #483;
+
+// added by blub
+
+string(string key) serverkey = #354;
+float(string s1, string s2) strcasecmp = #229;
+float(string s1, string s2, float len) strncasecmp = #230;
+float(string str, string sub, float startoffs) strstrofs = #221;
+//float(string str, string sub) strstrofs = #221;
+entity(float num) edict_num = #459;
+string(void) ReadPicture = #501;
+string(string filename) whichpack = #503;
+float(entity ent) num_for_edict = #512;
+float(string s, string separator1, ...) tokenizebyseparator = #479;
+string(string in) uri_unescape = #511;
+float(float caseinsensitive, string s, ...) crc16 = #494;
+string(string info, string key) infoget = #227;
+string(string info, string key, string value, ...) infoadd = #226;
+string(string in) uri_escape = #510;
+
+string keynumtostring(float keynum) = #520;
+string findkeysforcommand(string command) = #521;
+
+string(float ccase, float calpha, float cnum, string s, ...) strconv = #224;
+float(entity ent) wasfreed = #353;
+
+entity(vector org, float rad) findradius = #22;
+
+string(float uselocaltime, string format, ...) strftime = #478;
+float(float timer) gettime = #519;
+#define GETTIME_CDTRACK 4
+
+float(string s) tokenize_console = #514;
+float(float i) argv_start_index = #515;
+float(float i) argv_end_index = #516;
Property changes on: trunk/data/qcsrc/client/csqc_builtins.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/csqc_constants.qc
===================================================================
--- trunk/data/qcsrc/client/csqc_constants.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/csqc_constants.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,192 +1,192 @@
-const entity NULL = world;
-
-// Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask)
-const float MASK_ENGINE = 1;
-const float MASK_ENGINEVIEWMODELS = 2;
-const float MASK_NORMAL = 4;
-
-// Renderflag Constants (used for CSQC entities)
-const float RF_VIEWMODEL = 1;
-const float RF_EXTERNALMODEL = 2;
-const float RF_DEPTHHACK = 4;
-const float RF_ADDITIVE = 8;
-const float RF_USEAXIS = 16;
-
-// Viewflag Constants (use with R_SetView)
-const float VF_MIN = 1; //(vector)
-const float VF_MIN_X = 2; //(float)
-const float VF_MIN_Y = 3; //(float)
-const float VF_SIZE = 4; //(vector) (viewport size)
-const float VF_SIZE_Y = 5; //(float)
-const float VF_SIZE_X = 6; //(float)
-const float VF_VIEWPORT = 7; //(vector, vector)
-const float VF_FOV = 8; //(vector)
-const float VF_FOVX = 9; //(float)
-const float VF_FOVY = 10; //(float)
-const float VF_ORIGIN = 11; //(vector)
-const float VF_ORIGIN_X = 12; //(float)
-const float VF_ORIGIN_Y = 13; //(float)
-const float VF_ORIGIN_Z = 14; //(float)
-const float VF_ANGLES = 15; //(vector)
-const float VF_ANGLES_X = 16; //(float)
-const float VF_ANGLES_Y = 17; //(float)
-const float VF_ANGLES_Z = 18; //(float)
-const float VF_DRAWWORLD = 19; //(float)
-const float VF_DRAWENGINESBAR = 20; //(float)
-const float VF_DRAWCROSSHAIR = 21; //(float)
-const float VF_PERSPECTIVE = 200; //(float)
-
-const float VF_CL_VIEWANGLES = 33; //(vector)
-const float VF_CL_VIEWANGLES_X = 34; //(float)
-const float VF_CL_VIEWANGLES_Y = 35; //(float)
-const float VF_CL_VIEWANGLES_Z = 36; //(float)
-
-// Server Autosent Stat Constants
-const float STAT_HEALTH = 0;
-const float STAT_WEAPONMODEL = 2;
-const float STAT_AMMO = 3;
-const float STAT_ARMOR = 4;
-const float STAT_WEAPONFRAME = 5;
-const float STAT_SHELLS = 6;
-const float STAT_NAILS = 7;
-const float STAT_ROCKETS = 8;
-const float STAT_CELLS = 9;
-const float STAT_ACTIVEWEAPON = 10;
-const float STAT_TOTALSECRETS = 11;
-const float STAT_TOTALMONSTERS = 12;
-const float STAT_SECRETS = 13;
-const float STAT_MONSTERS = 14;
-const float STAT_ITEMS = 15;
-const float STAT_VIEWHEIGHT = 16;
-const float STAT_MOVEVARS_TICRATE = 240;
-const float STAT_MOVEVARS_TIMESCALE = 241;
-const float STAT_FRAGLIMIT = 235;
-const float STAT_TIMELIMIT = 236;
-const float STAT_MOVEVARS_GRAVITY = 242;
-
-// Sound Constants
-//const float CHAN_AUTO = 0;
-//const float CHAN_WEAPON = 1;
-//const float CHAN_VOICE = 2;
-//const float CHAN_ITEM = 3;
-//const float CHAN_BODY = 4;
-
-//const float ATTN_NONE = 0;
-//const float ATTN_NORM = 1;
-//const float ATTN_IDLE = 2;
-//const float ATTN_STATIC = 3;
-
-// Quake-style Point Contents
-const float CONTENT_EMPTY = -1;
-const float CONTENT_SOLID = -2;
-const float CONTENT_WATER = -3;
-const float CONTENT_SLIME = -4;
-const float CONTENT_LAVA = -5;
-const float CONTENT_SKY = -6;
-
-// Boolean Constants
-const float true = 1;
-const float false = 0;
-const float TRUE = 1;
-const float FALSE = 0;
-
-// Vector / Hull Constants
-const vector VEC_1 = '1 1 1';
-const vector VEC_0 = '0 0 0';
-const vector VEC_M1 = '-1 -1 -1';
-
-const vector VEC_HULL_MIN = '-16 -16 -24';
-const vector VEC_HULL_MAX = '16 16 32';
-
-// Effect Constants
-const float EF_NODRAW = 16;
-const float EF_ADDITIVE = 32;
-const float EF_BLUE = 64;
-const float EF_RED = 128;
-const float EF_FULLBRIGHT = 512;
-const float EF_FLAME = 1024;
-const float EF_STARDUST = 2048;
-const float EF_NOSHADOW = 4096;
-const float EF_NODEPTHTEST = 8192;
-
-// Quake Player Flag Constants
-const float PFL_ONGROUND = 1;
-const float PFL_CROUCH = 2;
-const float PFL_DEAD = 4;
-const float PFL_GIBBED = 8;
-
-// Quake Temporary Entity Constants
-const float TE_SPIKE = 0;
-const float TE_SUPERSPIKE = 1;
-const float TE_GUNSHOT = 2;
-const float TE_EXPLOSION = 3;
-const float TE_TAREXPLOSION = 4;
-const float TE_LIGHTNING1 = 5;
-const float TE_LIGHTNING2 = 6;
-const float TE_WIZSPIKE = 7;
-const float TE_KNIGHTSPIKE = 8;
-const float TE_LIGHTNING3 = 9;
-const float TE_LAVASPLASH = 10;
-const float TE_TELEPORT = 11;
-const float TE_EXPLOSION2 = 12;
-// Darkplaces Additions
-const float TE_EXPLOSIONRGB = 53;
-const float TE_GUNSHOTQUAD = 57;
-const float TE_EXPLOSIONQUAD = 70;
-
-// Math Constants
-const float M_PI = 3.14159265358979323846;
-const float EXTRA_LOW = -99999999;
-const float EXTRA_HIGH = 99999999;
-
-// Frik File Constants
-const float FILE_READ = 0;
-const float FILE_APPEND = 1;
-const float FILE_WRITE = 2;
-
-// Button values used by input_buttons
-const float BUTTON_ATTACK = 1;
-const float BUTTON_JUMP = 2;
-const float BUTTON_3 = 4;
-const float BUTTON_4 = 8;
-const float BUTTON_5 = 16;
-const float BUTTON_6 = 32;
-const float BUTTON7 = 64;
-const float BUTTON8 = 128;
-const float BUTTON_USE = 256;
-const float BUTTON_CHAT = 512;
-const float BUTTON_PRYDONCURSOR = 1024;
-const float BUTTON_9 = 2048;
-const float BUTTON_10 = 4096;
-const float BUTTON_11 = 8192;
-const float BUTTON_12 = 16384;
-const float BUTTON_13 = 32768;
-const float BUTTON_14 = 65536;
-const float BUTTON_15 = 131072;
-const float BUTTON_16 = 262144;
-
-
-const float DRAWFLAG_NORMAL = 0;
-const float DRAWFLAG_ADDITIVE = 1;
-const float DRAWFLAG_MODULATE = 2;
-const float DRAWFLAG_2XMODULATE = 3;
-const float DRAWFLAG_SCREEN = 4;
-const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon
-
-#define SOLID_NOT 0 // no interaction with other objects
-#define SOLID_TRIGGER 1 // touch on edge, but not blocking
-#define SOLID_BBOX 2 // touch on edge, block
-#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
-#define SOLID_BSP 4 // bsp clip, touch on edge, block
-#define SOLID_CORPSE 5 // same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
-
-float MOVE_NORMAL = 0; // same as FALSE
-float MOVE_NOMONSTERS = 1; // same as TRUE
-float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
-float MOVE_HITMODEL = 4;
-float MOVE_WORLDONLY = 3;
-
-float CAMERA_FREE = 1;
-float CAMERA_CHASE = 2;
-
-float EF_NOMODELFLAGS = 8388608;
+const entity NULL = world;
+
+// Mask Constants (set .drawmask on entities; use R_AddEntities to add all entities based on mask)
+const float MASK_ENGINE = 1;
+const float MASK_ENGINEVIEWMODELS = 2;
+const float MASK_NORMAL = 4;
+
+// Renderflag Constants (used for CSQC entities)
+const float RF_VIEWMODEL = 1;
+const float RF_EXTERNALMODEL = 2;
+const float RF_DEPTHHACK = 4;
+const float RF_ADDITIVE = 8;
+const float RF_USEAXIS = 16;
+
+// Viewflag Constants (use with R_SetView)
+const float VF_MIN = 1; //(vector)
+const float VF_MIN_X = 2; //(float)
+const float VF_MIN_Y = 3; //(float)
+const float VF_SIZE = 4; //(vector) (viewport size)
+const float VF_SIZE_Y = 5; //(float)
+const float VF_SIZE_X = 6; //(float)
+const float VF_VIEWPORT = 7; //(vector, vector)
+const float VF_FOV = 8; //(vector)
+const float VF_FOVX = 9; //(float)
+const float VF_FOVY = 10; //(float)
+const float VF_ORIGIN = 11; //(vector)
+const float VF_ORIGIN_X = 12; //(float)
+const float VF_ORIGIN_Y = 13; //(float)
+const float VF_ORIGIN_Z = 14; //(float)
+const float VF_ANGLES = 15; //(vector)
+const float VF_ANGLES_X = 16; //(float)
+const float VF_ANGLES_Y = 17; //(float)
+const float VF_ANGLES_Z = 18; //(float)
+const float VF_DRAWWORLD = 19; //(float)
+const float VF_DRAWENGINESBAR = 20; //(float)
+const float VF_DRAWCROSSHAIR = 21; //(float)
+const float VF_PERSPECTIVE = 200; //(float)
+
+const float VF_CL_VIEWANGLES = 33; //(vector)
+const float VF_CL_VIEWANGLES_X = 34; //(float)
+const float VF_CL_VIEWANGLES_Y = 35; //(float)
+const float VF_CL_VIEWANGLES_Z = 36; //(float)
+
+// Server Autosent Stat Constants
+const float STAT_HEALTH = 0;
+const float STAT_WEAPONMODEL = 2;
+const float STAT_AMMO = 3;
+const float STAT_ARMOR = 4;
+const float STAT_WEAPONFRAME = 5;
+const float STAT_SHELLS = 6;
+const float STAT_NAILS = 7;
+const float STAT_ROCKETS = 8;
+const float STAT_CELLS = 9;
+const float STAT_ACTIVEWEAPON = 10;
+const float STAT_TOTALSECRETS = 11;
+const float STAT_TOTALMONSTERS = 12;
+const float STAT_SECRETS = 13;
+const float STAT_MONSTERS = 14;
+const float STAT_ITEMS = 15;
+const float STAT_VIEWHEIGHT = 16;
+const float STAT_MOVEVARS_TICRATE = 240;
+const float STAT_MOVEVARS_TIMESCALE = 241;
+const float STAT_FRAGLIMIT = 235;
+const float STAT_TIMELIMIT = 236;
+const float STAT_MOVEVARS_GRAVITY = 242;
+
+// Sound Constants
+//const float CHAN_AUTO = 0;
+//const float CHAN_WEAPON = 1;
+//const float CHAN_VOICE = 2;
+//const float CHAN_ITEM = 3;
+//const float CHAN_BODY = 4;
+
+//const float ATTN_NONE = 0;
+//const float ATTN_NORM = 1;
+//const float ATTN_IDLE = 2;
+//const float ATTN_STATIC = 3;
+
+// Quake-style Point Contents
+const float CONTENT_EMPTY = -1;
+const float CONTENT_SOLID = -2;
+const float CONTENT_WATER = -3;
+const float CONTENT_SLIME = -4;
+const float CONTENT_LAVA = -5;
+const float CONTENT_SKY = -6;
+
+// Boolean Constants
+const float true = 1;
+const float false = 0;
+const float TRUE = 1;
+const float FALSE = 0;
+
+// Vector / Hull Constants
+const vector VEC_1 = '1 1 1';
+const vector VEC_0 = '0 0 0';
+const vector VEC_M1 = '-1 -1 -1';
+
+const vector VEC_HULL_MIN = '-16 -16 -24';
+const vector VEC_HULL_MAX = '16 16 32';
+
+// Effect Constants
+const float EF_NODRAW = 16;
+const float EF_ADDITIVE = 32;
+const float EF_BLUE = 64;
+const float EF_RED = 128;
+const float EF_FULLBRIGHT = 512;
+const float EF_FLAME = 1024;
+const float EF_STARDUST = 2048;
+const float EF_NOSHADOW = 4096;
+const float EF_NODEPTHTEST = 8192;
+
+// Quake Player Flag Constants
+const float PFL_ONGROUND = 1;
+const float PFL_CROUCH = 2;
+const float PFL_DEAD = 4;
+const float PFL_GIBBED = 8;
+
+// Quake Temporary Entity Constants
+const float TE_SPIKE = 0;
+const float TE_SUPERSPIKE = 1;
+const float TE_GUNSHOT = 2;
+const float TE_EXPLOSION = 3;
+const float TE_TAREXPLOSION = 4;
+const float TE_LIGHTNING1 = 5;
+const float TE_LIGHTNING2 = 6;
+const float TE_WIZSPIKE = 7;
+const float TE_KNIGHTSPIKE = 8;
+const float TE_LIGHTNING3 = 9;
+const float TE_LAVASPLASH = 10;
+const float TE_TELEPORT = 11;
+const float TE_EXPLOSION2 = 12;
+// Darkplaces Additions
+const float TE_EXPLOSIONRGB = 53;
+const float TE_GUNSHOTQUAD = 57;
+const float TE_EXPLOSIONQUAD = 70;
+
+// Math Constants
+const float M_PI = 3.14159265358979323846;
+const float EXTRA_LOW = -99999999;
+const float EXTRA_HIGH = 99999999;
+
+// Frik File Constants
+const float FILE_READ = 0;
+const float FILE_APPEND = 1;
+const float FILE_WRITE = 2;
+
+// Button values used by input_buttons
+const float BUTTON_ATTACK = 1;
+const float BUTTON_JUMP = 2;
+const float BUTTON_3 = 4;
+const float BUTTON_4 = 8;
+const float BUTTON_5 = 16;
+const float BUTTON_6 = 32;
+const float BUTTON7 = 64;
+const float BUTTON8 = 128;
+const float BUTTON_USE = 256;
+const float BUTTON_CHAT = 512;
+const float BUTTON_PRYDONCURSOR = 1024;
+const float BUTTON_9 = 2048;
+const float BUTTON_10 = 4096;
+const float BUTTON_11 = 8192;
+const float BUTTON_12 = 16384;
+const float BUTTON_13 = 32768;
+const float BUTTON_14 = 65536;
+const float BUTTON_15 = 131072;
+const float BUTTON_16 = 262144;
+
+
+const float DRAWFLAG_NORMAL = 0;
+const float DRAWFLAG_ADDITIVE = 1;
+const float DRAWFLAG_MODULATE = 2;
+const float DRAWFLAG_2XMODULATE = 3;
+const float DRAWFLAG_SCREEN = 4;
+const float DRAWFLAG_MIPMAP = 0x100; // only for R_BeginPolygon
+
+#define SOLID_NOT 0 // no interaction with other objects
+#define SOLID_TRIGGER 1 // touch on edge, but not blocking
+#define SOLID_BBOX 2 // touch on edge, block
+#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground
+#define SOLID_BSP 4 // bsp clip, touch on edge, block
+#define SOLID_CORPSE 5 // same as SOLID_BBOX, except it behaves as SOLID_NOT against SOLID_SLIDEBOX objects (players/monsters)
+
+float MOVE_NORMAL = 0; // same as FALSE
+float MOVE_NOMONSTERS = 1; // same as TRUE
+float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
+float MOVE_HITMODEL = 4;
+float MOVE_WORLDONLY = 3;
+
+float CAMERA_FREE = 1;
+float CAMERA_CHASE = 2;
+
+float EF_NOMODELFLAGS = 8388608;
Property changes on: trunk/data/qcsrc/client/csqc_constants.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/ctf.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/damage.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/effects.qc
===================================================================
--- trunk/data/qcsrc/client/effects.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/effects.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,100 +1,100 @@
-/*
-.vector fx_start;
-.vector fx_end;
-.float fx_with;
-.string fx_texture;
-.float fx_lifetime;
-
-void SUB_Remove()
-{ remove(self); }
-
-void b_draw()
-{
- //Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, 0, time * 3, '1 1 1', 0.7, DRAWFLAG_ADDITIVE);
- Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, (self.fx_with/256), 0, '1 1 1', 1, DRAWFLAG_ADDITIVE);
-
-}
-void b_make(vector s,vector e, string t,float l,float z)
-{
- entity b;
- b = spawn();
- b.fx_texture = t;
- b.fx_start = s;
- b.fx_end = e;
- b.fx_with = z;
- b.think = SUB_Remove;
- b.nextthink = time + l;
- b.draw = b_draw;
-
- //b.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
-}
-*/
-
-void cl_effetcs_lightningarc(vector from, vector to,float seglength,float drifts,float drifte,float branchfactor,float branchfactor_add)
-{
- vector direction,dirnew, pos, pos_l;
- float length, steps, steplength, i,drift;
-
- length = vlen(from - to);
- if(length < 1)
- return;
-
- steps = floor(length / seglength);
- if(steps < 1)
- {
- te_lightning1(world,from,to);
- return;
- }
-
- steplength = length / steps;
- direction = normalize(to - from);
- pos_l = from;
- if(length > seglength)
- {
- for(i = 1; i < steps; i += 1)
- {
- drift = drifts * (1 - (i / steps)) + drifte * (i / steps);
- dirnew = normalize(direction * (1 - drift) + randomvec() * drift);
- pos = pos_l + dirnew * steplength;
- te_lightning1(world,pos_l,pos);
- //b_make(pos_l, pos,"particles/lightning2",0.25,64);
- if(random() < branchfactor)
- cl_effetcs_lightningarc(pos, pos + (dirnew * length * 0.25),seglength,drifts,drifte,min(branchfactor + branchfactor_add,1),branchfactor_add);
-
- pos_l = pos;
- }
- te_lightning1(world,pos_l,to);
- //b_make(pos_l, to,"particles/lightning2",0.25,64);
-
- }
- else
- te_lightning1(world,from,to);
- //b_make(from, to,"particles/lightning2",0.25,64);
-
-}
-
-void Net_ReadLightningarc()
-{
- vector from, to;
-
- from_x = ReadCoord(); from_y = ReadCoord(); from_z = ReadCoord();
- to_x = ReadCoord(); to_y = ReadCoord(); to_z = ReadCoord();
-
- if(cvar("cl_effects_lightningarc_simple"))
- {
- te_lightning1(world,from,to);
- }
- else
- {
- float seglength, drifts, drifte, branchfactor, branchfactor_add;
-
- seglength = cvar("cl_effects_lightningarc_segmentlength");
- drifts = cvar("cl_effects_lightningarc_drift_start");
- drifte = cvar("cl_effects_lightningarc_drift_end");
- branchfactor = cvar("cl_effects_lightningarc_branchfactor_start");
- branchfactor = cvar("cl_effects_lightningarc_branchfactor_add");
-
- cl_effetcs_lightningarc(from,to,seglength,drifts,drifte,branchfactor,branchfactor_add);
- }
-
-}
+/*
+.vector fx_start;
+.vector fx_end;
+.float fx_with;
+.string fx_texture;
+.float fx_lifetime;
+
+void SUB_Remove()
+{ remove(self); }
+
+void b_draw()
+{
+ //Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, 0, time * 3, '1 1 1', 0.7, DRAWFLAG_ADDITIVE);
+ Draw_CylindricLine(self.fx_start, self.fx_end, self.fx_with, self.fx_texture, (self.fx_with/256), 0, '1 1 1', 1, DRAWFLAG_ADDITIVE);
+
+}
+void b_make(vector s,vector e, string t,float l,float z)
+{
+ entity b;
+ b = spawn();
+ b.fx_texture = t;
+ b.fx_start = s;
+ b.fx_end = e;
+ b.fx_with = z;
+ b.think = SUB_Remove;
+ b.nextthink = time + l;
+ b.draw = b_draw;
+
+ //b.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+}
+*/
+
+void cl_effetcs_lightningarc(vector from, vector to,float seglength,float drifts,float drifte,float branchfactor,float branchfactor_add)
+{
+ vector direction,dirnew, pos, pos_l;
+ float length, steps, steplength, i,drift;
+
+ length = vlen(from - to);
+ if(length < 1)
+ return;
+
+ steps = floor(length / seglength);
+ if(steps < 1)
+ {
+ te_lightning1(world,from,to);
+ return;
+ }
+
+ steplength = length / steps;
+ direction = normalize(to - from);
+ pos_l = from;
+ if(length > seglength)
+ {
+ for(i = 1; i < steps; i += 1)
+ {
+ drift = drifts * (1 - (i / steps)) + drifte * (i / steps);
+ dirnew = normalize(direction * (1 - drift) + randomvec() * drift);
+ pos = pos_l + dirnew * steplength;
+ te_lightning1(world,pos_l,pos);
+ //b_make(pos_l, pos,"particles/lightning2",0.25,64);
+ if(random() < branchfactor)
+ cl_effetcs_lightningarc(pos, pos + (dirnew * length * 0.25),seglength,drifts,drifte,min(branchfactor + branchfactor_add,1),branchfactor_add);
+
+ pos_l = pos;
+ }
+ te_lightning1(world,pos_l,to);
+ //b_make(pos_l, to,"particles/lightning2",0.25,64);
+
+ }
+ else
+ te_lightning1(world,from,to);
+ //b_make(from, to,"particles/lightning2",0.25,64);
+
+}
+
+void Net_ReadLightningarc()
+{
+ vector from, to;
+
+ from_x = ReadCoord(); from_y = ReadCoord(); from_z = ReadCoord();
+ to_x = ReadCoord(); to_y = ReadCoord(); to_z = ReadCoord();
+
+ if(cvar("cl_effects_lightningarc_simple"))
+ {
+ te_lightning1(world,from,to);
+ }
+ else
+ {
+ float seglength, drifts, drifte, branchfactor, branchfactor_add;
+
+ seglength = cvar("cl_effects_lightningarc_segmentlength");
+ drifts = cvar("cl_effects_lightningarc_drift_start");
+ drifte = cvar("cl_effects_lightningarc_drift_end");
+ branchfactor = cvar("cl_effects_lightningarc_branchfactor_start");
+ branchfactor = cvar("cl_effects_lightningarc_branchfactor_add");
+
+ cl_effetcs_lightningarc(from,to,seglength,drifts,drifte,branchfactor,branchfactor_add);
+ }
+
+}
Property changes on: trunk/data/qcsrc/client/effects.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/gibs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/hook.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/interpolate.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/interpolate.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/laser.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/main.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/mapvoting.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/movetypes.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/movetypes.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/particles.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/prandom.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/prandom.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/pre.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/projectile.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/client/rubble.qc
===================================================================
--- trunk/data/qcsrc/client/rubble.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/client/rubble.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,34 +1,34 @@
-.float creationtime;
-
-void RubbleDrop(entity list, void() deleteproc)
-{
- float t,tt;
- entity rub,old_rub;
-
- rub = findchainentity(owner,list);
- while(rub)
- {
- if(rub.creationtime > t)
- {
- old_rub = rub;
- tt = t;
- }
- rub = rub.chain;
- }
-
- rub = self;
- self = old_rub;
- deleteproc();
- self = rub;
-}
-
-entity RubbleNew(entity list)
-{
- entity rub;
-
- rub = spawn();
- rub.creationtime = time;
- rub.owner = list;
-
- return rub;
-}
+.float creationtime;
+
+void RubbleDrop(entity list, void() deleteproc)
+{
+ float t,tt;
+ entity rub,old_rub;
+
+ rub = findchainentity(owner,list);
+ while(rub)
+ {
+ if(rub.creationtime > t)
+ {
+ old_rub = rub;
+ tt = t;
+ }
+ rub = rub.chain;
+ }
+
+ rub = self;
+ self = old_rub;
+ deleteproc();
+ self = rub;
+}
+
+entity RubbleNew(entity list)
+{
+ entity rub;
+
+ rub = spawn();
+ rub.creationtime = time;
+ rub.owner = list;
+
+ return rub;
+}
Property changes on: trunk/data/qcsrc/client/rubble.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/sortlist.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/teamplay.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/teamradar.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/teamradar.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/wall.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/waypointsprites.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/client/waypointsprites.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/common/items.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/common/items.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/common/util-pre.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/bigbutton.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/bigcommandbutton.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/colorpicker.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/cvarlist.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/demolist.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_advanced.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_demo.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_join_serverinfo.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup_radar.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_multiplayer_playersetup_weapons.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_settings_audio.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_settings_misc_cvars.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/dialog_settings_network.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/modbutton.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/playerlist.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/skinlist.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/menu/nexuiz/weaponslist.c
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/bots_scripting.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/csqceffects.qc
===================================================================
--- trunk/data/qcsrc/server/csqceffects.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/csqceffects.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,13 +1,13 @@
-void te_csqc_lightningarc(vector from,vector to)
-{
- WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte(MSG_BROADCAST, TE_CSQC_LIGHTNINGARC);
-
- WriteCoord(MSG_BROADCAST, from_x);
- WriteCoord(MSG_BROADCAST, from_y);
- WriteCoord(MSG_BROADCAST, from_z);
- WriteCoord(MSG_BROADCAST, to_x);
- WriteCoord(MSG_BROADCAST, to_y);
- WriteCoord(MSG_BROADCAST, to_z);
-}
-
+void te_csqc_lightningarc(vector from,vector to)
+{
+ WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte(MSG_BROADCAST, TE_CSQC_LIGHTNINGARC);
+
+ WriteCoord(MSG_BROADCAST, from_x);
+ WriteCoord(MSG_BROADCAST, from_y);
+ WriteCoord(MSG_BROADCAST, from_z);
+ WriteCoord(MSG_BROADCAST, to_x);
+ WriteCoord(MSG_BROADCAST, to_y);
+ WriteCoord(MSG_BROADCAST, to_z);
+}
+
Property changes on: trunk/data/qcsrc/server/csqceffects.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/csqcprojectile.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/csqcprojectile.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/ent_cs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/func_breakable.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/g_hook.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/g_models.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/havocbot_ons.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/monsters/ai.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/monsters/defs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/monsters/fight.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/monsters/m_monsters.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/monsters/mode_management.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/movelib.qc
===================================================================
--- trunk/data/qcsrc/server/movelib.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/movelib.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,234 +1,234 @@
-.vector moveto;
-
-/**
- Simulate drag
- self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
-**/
-vector movelib_dragvec(float drag, float exp)
-{
- float lspeed,ldrag;
-
- lspeed = vlen(self.velocity);
- ldrag = lspeed * drag;
- ldrag = ldrag * (drag * exp);
- ldrag = 1 - (ldrag / lspeed);
-
- return self.velocity * ldrag;
-}
-
-/**
- Simulate drag
- self.velocity = movelib_vdrag(somespeed,0.01,0.7);
-**/
-float movelib_dragflt(float fspeed,float drag,float exp)
-{
- float ldrag;
-
- ldrag = fspeed * drag;
- ldrag = ldrag * ldrag * exp;
- ldrag = 1 - (ldrag / fspeed);
-
- return ldrag;
-}
-
-/**
- Do a inertia simulation based on velocity.
- Basicaly, this allows you to simulate loss of steering with higher speed.
- self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
-**/
-vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
-{
- float influense;
-
- influense = vlen(self.velocity) * (1 / vel_max);
-
- influense = bound(newmin,influense,oldmax);
-
- return (vel_new * (1 - influense)) + (self.velocity * influense);
-}
-
-vector movelib_inertmove(vector new_vel,float new_bias)
-{
- return new_vel * new_bias + self.velocity * (1-new_bias);
-}
-
-.float movelib_lastupdate;
-void movelib_move(vector force,float max_velocity,float drag,float mass,float breakforce)
-{
- float deltatime;
- float acceleration;
- float mspeed;
- vector breakvec;
-
- deltatime = time - self.movelib_lastupdate;
- if (deltatime > 0.15) deltatime = 0;
- self.movelib_lastupdate = time;
- if (!deltatime) return;
-
- mspeed = vlen(self.velocity);
-
- if (mass)
- acceleration = vlen(force) / mass;
- else
- acceleration = vlen(force);
-
- if (self.flags & FL_ONGROUND)
- {
- if (breakforce)
- {
- breakvec = (normalize(self.velocity) * (breakforce / mass) * deltatime);
- self.velocity = self.velocity - breakvec;
- }
-
- self.velocity = self.velocity + force * (acceleration * deltatime);
- }
-
- if (drag)
- self.velocity = movelib_dragvec(drag, 1);
-
- if (self.waterlevel > 1)
- {
- self.velocity = self.velocity + force * (acceleration * deltatime);
- self.velocity = self.velocity + '0 0 0.05' * sv_gravity * deltatime;
- }
- else
- self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
-
- mspeed = vlen(self.velocity);
-
- if (max_velocity)
- if (mspeed > max_velocity)
- self.velocity = normalize(self.velocity) * (mspeed - 50);//* max_velocity;
-}
-
-/*
-.float mass;
-.float side_friction;
-.float ground_friction;
-.float air_friction;
-.float water_friction;
-.float buoyancy;
-float movelib_deltatime;
-
-void movelib_startupdate()
-{
- movelib_deltatime = time - self.movelib_lastupdate;
-
- if (movelib_deltatime > 0.5)
- movelib_deltatime = 0;
-
- self.movelib_lastupdate = time;
-}
-
-void movelib_update(vector dir,float force)
-{
- vector acceleration;
- float old_speed;
- float ffriction,v_z;
-
- vector breakvec;
- vector old_dir;
- vector ggravity;
- vector old;
-
- if(!movelib_deltatime)
- return;
- v_z = self.velocity_z;
- old_speed = vlen(self.velocity);
- old_dir = normalize(self.velocity);
-
- //ggravity = (sv_gravity / self.mass) * '0 0 100';
- acceleration = (force / self.mass) * dir;
- //acceleration -= old_dir * (old_speed / self.mass);
- acceleration -= ggravity;
-
- if(self.waterlevel > 1)
- {
- ffriction = self.water_friction;
- acceleration += self.buoyancy * '0 0 1';
- }
- else
- if(self.flags & FL_ONGROUND)
- ffriction = self.ground_friction;
- else
- ffriction = self.air_friction;
-
- acceleration *= ffriction;
- //self.velocity = self.velocity * (ffriction * movelib_deltatime);
- self.velocity += acceleration * movelib_deltatime;
- self.velocity_z = v_z;
-
-}
-*/
-
-void movelib_move_simple(vector newdir,float velo,float blendrate)
-{
- self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo;
-}
-void movelib_beak_simple(float force)
-{
- float mspeed;
- vector mdir;
- float vz;
-
- mspeed = max(0,vlen(self.velocity) - force);
- mdir = normalize(self.velocity);
- vz = self.velocity_z;
- self.velocity = mdir * mspeed;
- self.velocity_z = vz;
-}
-
-
-void movelib_groundalign4point(float spring_length,float spring_up,float blendrate)
-{
- vector a,b,c,d,e,r,push_angle, ahead,side;
-
- push_angle_y = 0;
- r = (self.absmax + self.absmin) * 0.5 + (v_up * spring_up);
- e = v_up * spring_length;
-
- // Put springs slightly inside bbox
- ahead = v_forward * (self.maxs_x * 0.85);
- side = v_right * (self.maxs_y * 0.85);
-
- a = r + ahead + side;
- b = r + ahead - side;
- c = r - ahead + side;
- d = r - ahead - side;
-
- traceline(a, a - e,MOVE_NORMAL,self);
- a_z = (1 - trace_fraction);
- r = trace_endpos;
-
- traceline(b, b - e,MOVE_NORMAL,self);
- b_z = (1 - trace_fraction);
- r += trace_endpos;
-
- traceline(c, c - e,MOVE_NORMAL,self);
- c_z = (1 - trace_fraction);
- r += trace_endpos;
-
- traceline(d, d - e,MOVE_NORMAL,self);
- d_z = (1 - trace_fraction);
- r += trace_endpos;
-
- a_x = r_z;
- r = self.origin;
- r_z = r_z;
-
- push_angle_x = (a_z - c_z) * 45;
- push_angle_x += (b_z - d_z) * 45;
-
- push_angle_z = (b_z - a_z) * 45;
- push_angle_z += (d_z - c_z) * 45;
-
- //self.angles_x += push_angle_x * 0.95;
- //self.angles_z += push_angle_z * 0.95;
-
- self.angles_x = ((1-blendrate) * self.angles_x) + (push_angle_x * blendrate);
- self.angles_z = ((1-blendrate) * self.angles_z) + (push_angle_z * blendrate);
-
- //a = self.origin;
- setorigin(self,r);
-}
-
+.vector moveto;
+
+/**
+ Simulate drag
+ self.velocity = movelib_vdrag(self.velocity,0.02,0.5);
+**/
+vector movelib_dragvec(float drag, float exp)
+{
+ float lspeed,ldrag;
+
+ lspeed = vlen(self.velocity);
+ ldrag = lspeed * drag;
+ ldrag = ldrag * (drag * exp);
+ ldrag = 1 - (ldrag / lspeed);
+
+ return self.velocity * ldrag;
+}
+
+/**
+ Simulate drag
+ self.velocity = movelib_vdrag(somespeed,0.01,0.7);
+**/
+float movelib_dragflt(float fspeed,float drag,float exp)
+{
+ float ldrag;
+
+ ldrag = fspeed * drag;
+ ldrag = ldrag * ldrag * exp;
+ ldrag = 1 - (ldrag / fspeed);
+
+ return ldrag;
+}
+
+/**
+ Do a inertia simulation based on velocity.
+ Basicaly, this allows you to simulate loss of steering with higher speed.
+ self.velocity = movelib_inertia_fromspeed(self.velocity,newvel,1000,0.1,0.9);
+**/
+vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
+{
+ float influense;
+
+ influense = vlen(self.velocity) * (1 / vel_max);
+
+ influense = bound(newmin,influense,oldmax);
+
+ return (vel_new * (1 - influense)) + (self.velocity * influense);
+}
+
+vector movelib_inertmove(vector new_vel,float new_bias)
+{
+ return new_vel * new_bias + self.velocity * (1-new_bias);
+}
+
+.float movelib_lastupdate;
+void movelib_move(vector force,float max_velocity,float drag,float mass,float breakforce)
+{
+ float deltatime;
+ float acceleration;
+ float mspeed;
+ vector breakvec;
+
+ deltatime = time - self.movelib_lastupdate;
+ if (deltatime > 0.15) deltatime = 0;
+ self.movelib_lastupdate = time;
+ if (!deltatime) return;
+
+ mspeed = vlen(self.velocity);
+
+ if (mass)
+ acceleration = vlen(force) / mass;
+ else
+ acceleration = vlen(force);
+
+ if (self.flags & FL_ONGROUND)
+ {
+ if (breakforce)
+ {
+ breakvec = (normalize(self.velocity) * (breakforce / mass) * deltatime);
+ self.velocity = self.velocity - breakvec;
+ }
+
+ self.velocity = self.velocity + force * (acceleration * deltatime);
+ }
+
+ if (drag)
+ self.velocity = movelib_dragvec(drag, 1);
+
+ if (self.waterlevel > 1)
+ {
+ self.velocity = self.velocity + force * (acceleration * deltatime);
+ self.velocity = self.velocity + '0 0 0.05' * sv_gravity * deltatime;
+ }
+ else
+ self.velocity = self.velocity + '0 0 -1' * sv_gravity * deltatime;
+
+ mspeed = vlen(self.velocity);
+
+ if (max_velocity)
+ if (mspeed > max_velocity)
+ self.velocity = normalize(self.velocity) * (mspeed - 50);//* max_velocity;
+}
+
+/*
+.float mass;
+.float side_friction;
+.float ground_friction;
+.float air_friction;
+.float water_friction;
+.float buoyancy;
+float movelib_deltatime;
+
+void movelib_startupdate()
+{
+ movelib_deltatime = time - self.movelib_lastupdate;
+
+ if (movelib_deltatime > 0.5)
+ movelib_deltatime = 0;
+
+ self.movelib_lastupdate = time;
+}
+
+void movelib_update(vector dir,float force)
+{
+ vector acceleration;
+ float old_speed;
+ float ffriction,v_z;
+
+ vector breakvec;
+ vector old_dir;
+ vector ggravity;
+ vector old;
+
+ if(!movelib_deltatime)
+ return;
+ v_z = self.velocity_z;
+ old_speed = vlen(self.velocity);
+ old_dir = normalize(self.velocity);
+
+ //ggravity = (sv_gravity / self.mass) * '0 0 100';
+ acceleration = (force / self.mass) * dir;
+ //acceleration -= old_dir * (old_speed / self.mass);
+ acceleration -= ggravity;
+
+ if(self.waterlevel > 1)
+ {
+ ffriction = self.water_friction;
+ acceleration += self.buoyancy * '0 0 1';
+ }
+ else
+ if(self.flags & FL_ONGROUND)
+ ffriction = self.ground_friction;
+ else
+ ffriction = self.air_friction;
+
+ acceleration *= ffriction;
+ //self.velocity = self.velocity * (ffriction * movelib_deltatime);
+ self.velocity += acceleration * movelib_deltatime;
+ self.velocity_z = v_z;
+
+}
+*/
+
+void movelib_move_simple(vector newdir,float velo,float blendrate)
+{
+ self.velocity = self.velocity * (1 - blendrate) + (newdir * blendrate) * velo;
+}
+void movelib_beak_simple(float force)
+{
+ float mspeed;
+ vector mdir;
+ float vz;
+
+ mspeed = max(0,vlen(self.velocity) - force);
+ mdir = normalize(self.velocity);
+ vz = self.velocity_z;
+ self.velocity = mdir * mspeed;
+ self.velocity_z = vz;
+}
+
+
+void movelib_groundalign4point(float spring_length,float spring_up,float blendrate)
+{
+ vector a,b,c,d,e,r,push_angle, ahead,side;
+
+ push_angle_y = 0;
+ r = (self.absmax + self.absmin) * 0.5 + (v_up * spring_up);
+ e = v_up * spring_length;
+
+ // Put springs slightly inside bbox
+ ahead = v_forward * (self.maxs_x * 0.85);
+ side = v_right * (self.maxs_y * 0.85);
+
+ a = r + ahead + side;
+ b = r + ahead - side;
+ c = r - ahead + side;
+ d = r - ahead - side;
+
+ traceline(a, a - e,MOVE_NORMAL,self);
+ a_z = (1 - trace_fraction);
+ r = trace_endpos;
+
+ traceline(b, b - e,MOVE_NORMAL,self);
+ b_z = (1 - trace_fraction);
+ r += trace_endpos;
+
+ traceline(c, c - e,MOVE_NORMAL,self);
+ c_z = (1 - trace_fraction);
+ r += trace_endpos;
+
+ traceline(d, d - e,MOVE_NORMAL,self);
+ d_z = (1 - trace_fraction);
+ r += trace_endpos;
+
+ a_x = r_z;
+ r = self.origin;
+ r_z = r_z;
+
+ push_angle_x = (a_z - c_z) * 45;
+ push_angle_x += (b_z - d_z) * 45;
+
+ push_angle_z = (b_z - a_z) * 45;
+ push_angle_z += (d_z - c_z) * 45;
+
+ //self.angles_x += push_angle_x * 0.95;
+ //self.angles_z += push_angle_z * 0.95;
+
+ self.angles_x = ((1-blendrate) * self.angles_x) + (push_angle_x * blendrate);
+ self.angles_z = ((1-blendrate) * self.angles_z) + (push_angle_z * blendrate);
+
+ //a = self.origin;
+ setorigin(self,r);
+}
+
Property changes on: trunk/data/qcsrc/server/movelib.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/nexball.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/costs.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/costs.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/costs.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,144 +1,144 @@
-float pathlib_g_static(entity parent,vector to, float static_cost)
-{
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_static_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_euclidean(entity parent,vector to, float static_cost)
-{
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-
-float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-
-
-/**
- Manhattan Menas we expect to move up,down left or right
- No diagonal moves espected. (like moving bewteen city blocks)
-**/
-float pathlib_h_manhattan(vector a,vector b)
-{
- //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
-
- float h;
- h = fabs(a_x - b_x);
- h += fabs(a_y - b_y);
- h *= pathlib_gridsize;
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves
- to have teh same cost.
-**/
-float pathlib_h_diagonal(vector a,vector b)
-{
- //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
- float h,x,y;
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
- h = pathlib_movecost * max(x,y);
-
- return h;
-}
-
-/**
- This heuristic only considers the stright line distance.
- Will usualy mean a lower H then G meaning A* Will speand more
- and run slower.
-**/
-float pathlib_h_euclidean(vector a,vector b)
-{
- return vlen(a - b);
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-**/
-float pathlib_h_diagonal2(vector a,vector b)
-{
- float h_diag,h_str,h,x,y;
-
- /*
- h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
- */
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
-
- h_diag = min(x,y);
- h_str = x + y;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-**/
-float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
-{
- float h_diag,h_str,h,x,y,z;
-
- //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
- x = fabs(point_x - end_x);
- y = fabs(point_y - end_y);
- z = fabs(point_z - end_z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- float m;
- vector d1,d2;
-
- d1 = normalize(preprev - point);
- d2 = normalize(prev - point);
- m = vlen(d1-d2);
-
- return h * m;
-}
-
-
-float pathlib_h_diagonal3(vector a,vector b)
-{
- float h_diag,h_str,h,x,y,z;
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
- z = fabs(a_z - b_z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
+float pathlib_g_static(entity parent,vector to, float static_cost)
+{
+ return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_static_water(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_euclidean(entity parent,vector to, float static_cost)
+{
+ return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+
+float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+
+
+/**
+ Manhattan Menas we expect to move up,down left or right
+ No diagonal moves espected. (like moving bewteen city blocks)
+**/
+float pathlib_h_manhattan(vector a,vector b)
+{
+ //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
+
+ float h;
+ h = fabs(a_x - b_x);
+ h += fabs(a_y - b_y);
+ h *= pathlib_gridsize;
+
+ return h;
+}
+
+/**
+ This heuristic consider both stright and disagonal moves
+ to have teh same cost.
+**/
+float pathlib_h_diagonal(vector a,vector b)
+{
+ //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
+ float h,x,y;
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ h = pathlib_movecost * max(x,y);
+
+ return h;
+}
+
+/**
+ This heuristic only considers the stright line distance.
+ Will usualy mean a lower H then G meaning A* Will speand more
+ and run slower.
+**/
+float pathlib_h_euclidean(vector a,vector b)
+{
+ return vlen(a - b);
+}
+
+/**
+ This heuristic consider both stright and disagonal moves,
+ But has a separate cost for diagonal moves.
+**/
+float pathlib_h_diagonal2(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y;
+
+ /*
+ h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+ */
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+
+ h_diag = min(x,y);
+ h_str = x + y;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h;
+}
+
+/**
+ This heuristic consider both stright and disagonal moves,
+ But has a separate cost for diagonal moves.
+**/
+float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+ x = fabs(point_x - end_x);
+ y = fabs(point_y - end_y);
+ z = fabs(point_z - end_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ float m;
+ vector d1,d2;
+
+ d1 = normalize(preprev - point);
+ d2 = normalize(prev - point);
+ m = vlen(d1-d2);
+
+ return h * m;
+}
+
+
+float pathlib_h_diagonal3(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ z = fabs(a_z - b_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h;
+}
Property changes on: trunk/data/qcsrc/server/pathlib/costs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/debug.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/debug.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/debug.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,117 +1,117 @@
-
-void mark_error(vector where,float lifetime);
-void mark_info(vector where,float lifetime);
-entity mark_misc(vector where,float lifetime);
-
-
-void pathlib_showpath(entity start)
-{
- entity e;
- e = start;
- while(e.path_next)
- {
- te_lightning1(e,e.origin,e.path_next.origin);
- e = e.path_next;
- }
-}
-
-void path_dbg_think()
-{
- pathlib_showpath(self);
- self.nextthink = time + 1;
-}
-
-void __showpath2_think()
-{
- mark_info(self.origin,1);
- if(self.path_next)
- {
- self.path_next.think = __showpath2_think;
- self.path_next.nextthink = time + 0.15;
- }
- else
- {
- self.owner.think = __showpath2_think;
- self.owner.nextthink = time + 0.15;
- }
-}
-
-void pathlib_showpath2(entity path)
-{
- path.think = __showpath2_think;
- path.nextthink = time;
-}
-
-
-void pathlib_showsquare2(entity node ,vector ncolor,float align)
-{
-
- node.alpha = 0.25;
- node.scale = pathlib_gridsize / 512.001;
- node.solid = SOLID_NOT;
-
- setmodel(node,"models/pathlib/square.md3");
- setorigin(node,node.origin);
- node.colormod = ncolor;
-
- if(align)
- {
- traceline(node.origin + '0 0 32',node.origin - '0 0 128',MOVE_WORLDONLY,node);
- node.angles = vectoangles(trace_plane_normal);
- node.angles_x -= 90;
- }
-}
-
-void pathlib_showsquare(vector where,float goodsquare,float lifetime)
-{
- entity s;
-
- if(!lifetime)
- lifetime = time + 30;
- else
- lifetime += time;
-
- s = spawn();
- s.alpha = 0.25;
- s.think = SUB_Remove;
- s.nextthink = lifetime;
- s.scale = pathlib_gridsize / 512.001;
- s.solid = SOLID_NOT;
-
- if(goodsquare)
- setmodel(s,"models/pathlib/goodsquare.md3");
- else
- setmodel(s,"models/pathlib/badsquare.md3");
-
-
-
- traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,s);
-
- s.angles = vectoangles(trace_plane_normal);
- s.angles_x -= 90;
- setorigin(s,where);
-}
-
-void pathlib_showedge(vector where,float lifetime,float rot)
-{
- entity e;
-
- if(!lifetime)
- lifetime = time + 30;
- else
- lifetime += time;
-
- e = spawn();
- e.alpha = 0.25;
- e.think = SUB_Remove;
- e.nextthink = lifetime;
- e.scale = pathlib_gridsize / 512;
- e.solid = SOLID_NOT;
- setorigin(e,where);
- setmodel(e,"models/pathlib/edge.md3");
- //traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,e);
- //e.angles = vectoangles(trace_plane_normal);
- e.angles_y = rot;
- //e.angles_x += 90;
-
-}
+
+void mark_error(vector where,float lifetime);
+void mark_info(vector where,float lifetime);
+entity mark_misc(vector where,float lifetime);
+
+
+void pathlib_showpath(entity start)
+{
+ entity e;
+ e = start;
+ while(e.path_next)
+ {
+ te_lightning1(e,e.origin,e.path_next.origin);
+ e = e.path_next;
+ }
+}
+
+void path_dbg_think()
+{
+ pathlib_showpath(self);
+ self.nextthink = time + 1;
+}
+
+void __showpath2_think()
+{
+ mark_info(self.origin,1);
+ if(self.path_next)
+ {
+ self.path_next.think = __showpath2_think;
+ self.path_next.nextthink = time + 0.15;
+ }
+ else
+ {
+ self.owner.think = __showpath2_think;
+ self.owner.nextthink = time + 0.15;
+ }
+}
+
+void pathlib_showpath2(entity path)
+{
+ path.think = __showpath2_think;
+ path.nextthink = time;
+}
+
+
+void pathlib_showsquare2(entity node ,vector ncolor,float align)
+{
+
+ node.alpha = 0.25;
+ node.scale = pathlib_gridsize / 512.001;
+ node.solid = SOLID_NOT;
+
+ setmodel(node,"models/pathlib/square.md3");
+ setorigin(node,node.origin);
+ node.colormod = ncolor;
+
+ if(align)
+ {
+ traceline(node.origin + '0 0 32',node.origin - '0 0 128',MOVE_WORLDONLY,node);
+ node.angles = vectoangles(trace_plane_normal);
+ node.angles_x -= 90;
+ }
+}
+
+void pathlib_showsquare(vector where,float goodsquare,float lifetime)
+{
+ entity s;
+
+ if(!lifetime)
+ lifetime = time + 30;
+ else
+ lifetime += time;
+
+ s = spawn();
+ s.alpha = 0.25;
+ s.think = SUB_Remove;
+ s.nextthink = lifetime;
+ s.scale = pathlib_gridsize / 512.001;
+ s.solid = SOLID_NOT;
+
+ if(goodsquare)
+ setmodel(s,"models/pathlib/goodsquare.md3");
+ else
+ setmodel(s,"models/pathlib/badsquare.md3");
+
+
+
+ traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,s);
+
+ s.angles = vectoangles(trace_plane_normal);
+ s.angles_x -= 90;
+ setorigin(s,where);
+}
+
+void pathlib_showedge(vector where,float lifetime,float rot)
+{
+ entity e;
+
+ if(!lifetime)
+ lifetime = time + 30;
+ else
+ lifetime += time;
+
+ e = spawn();
+ e.alpha = 0.25;
+ e.think = SUB_Remove;
+ e.nextthink = lifetime;
+ e.scale = pathlib_gridsize / 512;
+ e.solid = SOLID_NOT;
+ setorigin(e,where);
+ setmodel(e,"models/pathlib/edge.md3");
+ //traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,e);
+ //e.angles = vectoangles(trace_plane_normal);
+ e.angles_y = rot;
+ //e.angles_x += 90;
+
+}
Property changes on: trunk/data/qcsrc/server/pathlib/debug.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/expandnode.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/expandnode.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/expandnode.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,196 +1,196 @@
-vector plib_points2[8];
-vector plib_points[8];
-float plib_fvals[8];
-
-float pathlib_expandnode_starf(entity node, vector start, vector goal)
-{
- vector where,f,r,t;
- float i,fc,fc2,c;
- entity nap;
-
- where = node.origin;
-
- f = PLIB_FORWARD * pathlib_gridsize;
- r = PLIB_RIGHT * pathlib_gridsize;
-
- // Forward
- plib_points[0] = where + f;
-
- // Back
- plib_points[1] = where - f;
-
- // Right
- plib_points[2] = where + r;
-
- // Left
- plib_points[3] = where - r;
-
- // Forward-right
- plib_points[4] = where + f + r;
-
- // Forward-left
- plib_points[5] = where + f - r;
-
- // Back-right
- plib_points[6] = where - f + r;
-
- // Back-left
- plib_points[7] = where - f - r;
-
- for(i=0;i < 8; ++i)
- {
- t = plib_points[i];
- fc = pathlib_heuristic(t,goal) + pathlib_cost(node,t,pathlib_gridsize);
- plib_fvals[i] = fc;
-
- }
-
- fc = plib_fvals[0];
- plib_points2[0] = plib_points[0];
- vector bp;
- bp = plib_points[0];
- for(i = 0; i < 8; ++i)
- {
- c = 0;
- nap = pathlib_nodeatpoint(plib_points[i]);
- if(nap)
- if(nap.owner == openlist)
- c = 1;
- else
- c = 1;
-
- if(c)
- if(plib_fvals[i] < fc)
- {
- bp = plib_points[i];
- fc = plib_fvals[i];
- plib_points2[fc2] = plib_points[i];
- ++fc2;
- }
-
- /*
- nap = pathlib_nodeatpoint(plib_points[i]);
- if(nap)
- if not nap.owner == closedlist)
- {
- }
- */
- }
-
- pathlib_makenode(node,start,bp,goal,pathlib_gridsize);
-
- for(i = 0; i < 3; ++i)
- {
- pathlib_makenode(node,start,plib_points2[i],goal,pathlib_gridsize);
- }
-
- return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_star(entity node, vector start, vector goal)
-{
- vector point,where,f,r;
-
- where = node.origin;
-
- f = PLIB_FORWARD * pathlib_gridsize;
- r = PLIB_RIGHT * pathlib_gridsize;
-
- // Forward
- point = where + f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Back
- point = where - f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Right
- point = where + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Left
- point = where - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Forward-right
- point = where + f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Forward-left
- point = where + f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-right
- point = where - f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-left
- point = where - f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_octagon(entity node, vector start, vector goal)
-{
- vector point,where,f,r;
-
- where = node.origin;
-
- f = PLIB_FORWARD * pathlib_gridsize;
- r = PLIB_RIGHT * pathlib_gridsize;
-
- // Forward
- point = where + f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Back
- point = where - f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Right
- point = where + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Left
- point = where - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- f = PLIB_FORWARD * pathlib_gridsize * 0.5;
- r = PLIB_RIGHT * pathlib_gridsize * 0.5;
-
- // Forward-right
- point = where + f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-
- // Forward-left
- point = where + f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-
- // Back-right
- point = where - f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Back-left
- point = where - f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_box(entity node, vector start, vector goal)
-{
- vector v;
-
- for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
- for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
- for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
- {
- //if(vlen(v - node.origin))
- pathlib_makenode(node,start,v,goal,pathlib_movecost);
- }
-
- return pathlib_open_cnt;
-}
+vector plib_points2[8];
+vector plib_points[8];
+float plib_fvals[8];
+
+float pathlib_expandnode_starf(entity node, vector start, vector goal)
+{
+ vector where,f,r,t;
+ float i,fc,fc2,c;
+ entity nap;
+
+ where = node.origin;
+
+ f = PLIB_FORWARD * pathlib_gridsize;
+ r = PLIB_RIGHT * pathlib_gridsize;
+
+ // Forward
+ plib_points[0] = where + f;
+
+ // Back
+ plib_points[1] = where - f;
+
+ // Right
+ plib_points[2] = where + r;
+
+ // Left
+ plib_points[3] = where - r;
+
+ // Forward-right
+ plib_points[4] = where + f + r;
+
+ // Forward-left
+ plib_points[5] = where + f - r;
+
+ // Back-right
+ plib_points[6] = where - f + r;
+
+ // Back-left
+ plib_points[7] = where - f - r;
+
+ for(i=0;i < 8; ++i)
+ {
+ t = plib_points[i];
+ fc = pathlib_heuristic(t,goal) + pathlib_cost(node,t,pathlib_gridsize);
+ plib_fvals[i] = fc;
+
+ }
+
+ fc = plib_fvals[0];
+ plib_points2[0] = plib_points[0];
+ vector bp;
+ bp = plib_points[0];
+ for(i = 0; i < 8; ++i)
+ {
+ c = 0;
+ nap = pathlib_nodeatpoint(plib_points[i]);
+ if(nap)
+ if(nap.owner == openlist)
+ c = 1;
+ else
+ c = 1;
+
+ if(c)
+ if(plib_fvals[i] < fc)
+ {
+ bp = plib_points[i];
+ fc = plib_fvals[i];
+ plib_points2[fc2] = plib_points[i];
+ ++fc2;
+ }
+
+ /*
+ nap = pathlib_nodeatpoint(plib_points[i]);
+ if(nap)
+ if not nap.owner == closedlist)
+ {
+ }
+ */
+ }
+
+ pathlib_makenode(node,start,bp,goal,pathlib_gridsize);
+
+ for(i = 0; i < 3; ++i)
+ {
+ pathlib_makenode(node,start,plib_points2[i],goal,pathlib_gridsize);
+ }
+
+ return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_star(entity node, vector start, vector goal)
+{
+ vector point,where,f,r;
+
+ where = node.origin;
+
+ f = PLIB_FORWARD * pathlib_gridsize;
+ r = PLIB_RIGHT * pathlib_gridsize;
+
+ // Forward
+ point = where + f;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Back
+ point = where - f;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Right
+ point = where + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Left
+ point = where - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Forward-right
+ point = where + f + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Forward-left
+ point = where + f - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-right
+ point = where - f + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-left
+ point = where - f - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_octagon(entity node, vector start, vector goal)
+{
+ vector point,where,f,r;
+
+ where = node.origin;
+
+ f = PLIB_FORWARD * pathlib_gridsize;
+ r = PLIB_RIGHT * pathlib_gridsize;
+
+ // Forward
+ point = where + f;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Back
+ point = where - f;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Right
+ point = where + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Left
+ point = where - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ f = PLIB_FORWARD * pathlib_gridsize * 0.5;
+ r = PLIB_RIGHT * pathlib_gridsize * 0.5;
+
+ // Forward-right
+ point = where + f + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+
+ // Forward-left
+ point = where + f - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+
+ // Back-right
+ point = where - f + r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Back-left
+ point = where - f - r;
+ pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_box(entity node, vector start, vector goal)
+{
+ vector v;
+
+ for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
+ for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
+ for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
+ {
+ //if(vlen(v - node.origin))
+ pathlib_makenode(node,start,v,goal,pathlib_movecost);
+ }
+
+ return pathlib_open_cnt;
+}
Property changes on: trunk/data/qcsrc/server/pathlib/expandnode.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/main.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/main.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/main.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,534 +1,534 @@
-void pathlib_deletepath(entity start)
-{
- entity e;
-
- e = findchainentity(owner, start);
- while(e)
- {
- e.think = SUB_Remove;
- e.nextthink = time;
- e = e.chain;
- }
-}
-
-//#define PATHLIB_NODEEXPIRE 0.05
-#define PATHLIB_NODEEXPIRE 20
-
-void dumpnode(entity n)
-{
- n.is_path_node = FALSE;
- n.think = SUB_Remove;
- n.nextthink = time;
-}
-
-entity pathlib_mknode(vector where,entity parent)
-{
- entity node;
-
- node = pathlib_nodeatpoint(where);
- if(node)
- {
- mark_error(where,60);
- return node;
- }
-
- node = spawn();
-
- node.think = SUB_Remove;
- node.nextthink = time + PATHLIB_NODEEXPIRE;
- node.is_path_node = TRUE;
- node.owner = openlist;
- node.path_prev = parent;
-
- setmodel(node,"models/pathlib/square.md3");
- setsize(node,'0 0 0','0 0 0');
- node.colormod = randomvec() * 2;
- node.alpha = 0.25;
- node.scale = pathlib_gridsize / 512.001;
-
- //pathlib_showsquare2(node,'1 1 1',0);//(node.medium & CONTENT_EMPTY));
- setorigin(node, where);
- node.medium = pointcontents(where);
-
- mark_info(where,60);
- //pathlib_showsquare(where,1,30);
-
-
- ++pathlib_made_cnt;
- ++pathlib_open_cnt;
-
- return node;
-}
-
-float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
-{
- entity node;
- float h,g,f,doedge;
- vector where;
-
- ++pathlib_searched_cnt;
-
- if(inwater(parent.origin))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_swimnode;
- }
- else
- {
- if(inwater(to))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_walknode;
- }
- else
- {
- //if(edge_check(parent.origin))
- // return 0;
-
- pathlib_expandnode = pathlib_expandnode_star;
- pathlib_movenode = pathlib_walknode;
- doedge = 1;
- }
- }
-
- node = pathlib_nodeatpoint(to);
- if(node)
- {
- ++pathlib_merge_cnt;
-
- if(node.owner == openlist)
- {
- h = pathlib_heuristic(node.origin,goal);
- g = pathlib_cost(parent,node.origin,cost);
- f = g + h;
-
- if(node.pathlib_node_g > g)
- {
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
-
- node.path_prev = parent;
- }
-
- if not (best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
- }
-
- return 1;
- }
-
- where = pathlib_movenode(parent.origin,to,0);
- if not(pathlib_movenode_goodnode)
- return 0;
-
- if(pathlib_nodeatpoint(where))
- {
- dprint("NAP WHERE :",vtos(where),"\n");
- dprint("not NAP TO:",vtos(to),"\n");
- dprint("NAP-NNAP:",ftos(vlen(to-where)),"\n\n");
- return 0;
- }
-
- if(doedge)
- if not (tile_check(where))
- return 0;
-
- h = pathlib_heuristic(where,goal);
- g = pathlib_cost(parent,where,cost);
- f = g + h;
-
-
- /*
- node = findradius(where,pathlib_gridsize * 0.5);
- while(node)
- {
- if(node.is_path_node == TRUE)
- {
- ++pathlib_merge_cnt;
- if(node.owner == openlist)
- {
- if(node.pathlib_node_g > g)
- {
- //pathlib_movenode(where,node.origin,0);
- //if(pathlib_movenode_goodnode)
- //{
- //mark_error(node.origin + '0 0 128',30);
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
- node.path_prev = parent;
- //}
- }
-
- if not (best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
- }
-
- return 1;
- }
- node = node.chain;
- }
- */
-
- node = pathlib_mknode(where,parent);
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
-
- if not (best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
-
- return 1;
-}
-
-entity pathlib_getbestopen()
-{
- entity node;
- entity bestnode;
-
- if(best_open_node)
- {
- ++pathlib_bestcash_hits;
- pathlib_bestcash_saved += pathlib_open_cnt;
-
- return best_open_node;
- }
-
- node = findchainentity(owner,openlist);
- if(!node)
- return world;
-
- bestnode = node;
- while(node)
- {
- ++pathlib_bestopen_seached;
- if(node.pathlib_node_f < bestnode.pathlib_node_f)
- bestnode = node;
-
- node = node.chain;
- }
-
- return bestnode;
-}
-
-void pathlib_close_node(entity node,vector goal)
-{
-
- if(node.owner == closedlist)
- {
- dprint("Pathlib: Tried to close a closed node!\n");
- return;
- }
-
- if(node == best_open_node)
- best_open_node = world;
-
- ++pathlib_closed_cnt;
- --pathlib_open_cnt;
-
- node.owner = closedlist;
-
- if(vlen(node.origin - goal) <= pathlib_gridsize)
- {
- vector goalmove;
-
- goalmove = pathlib_walknode(node.origin,goal,1);
- if(pathlib_movenode_goodnode)
- {
- goal_node = node;
- pathlib_foundgoal = TRUE;
- }
- }
-}
-
-void pathlib_cleanup()
-{
- best_open_node = world;
-
- //return;
-
- entity node;
-
- node = findfloat(world,is_path_node, TRUE);
- while(node)
- {
- /*
- node.owner = openlist;
- node.pathlib_node_g = 0;
- node.pathlib_node_h = 0;
- node.pathlib_node_f = 0;
- node.path_prev = world;
- */
-
- dumpnode(node);
- node = findfloat(node,is_path_node, TRUE);
- }
-
- if(openlist)
- remove(openlist);
-
- if(closedlist)
- remove(closedlist);
-
- openlist = world;
- closedlist = world;
-
-}
-
-float Cosine_Interpolate(float a, float b, float x)
-{
- float ft,f;
-
- ft = x * 3.1415927;
- f = (1 - cos(ft)) * 0.5;
-
- return a*(1-f) + b*f;
-}
-
-float buildpath_nodefilter_directional(vector n,vector c,vector p)
-{
- vector d1,d2;
-
- d2 = normalize(p - c);
- d1 = normalize(c - n);
-
- if(vlen(d1-d2) < 0.25)
- {
- //mark_error(c,30);
- return 1;
- }
- //mark_info(c,30);
- return 0;
-}
-
-float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
-{
- pathlib_walknode(p,n,1);
- if(pathlib_movenode_goodnode)
- return 1;
-
- return 0;
-}
-
-entity path_build(entity next, vector where, entity prev, entity start)
-{
- entity path;
-
- if(prev && next)
- if(buildpath_nodefilter)
- if(buildpath_nodefilter(next.origin,where,prev.origin))
- return next;
-
-
- path = spawn();
- path.owner = start;
- path.path_next = next;
-
- setorigin(path,where);
-
- if(!next)
- path.classname = "path_end";
- else
- {
- if(!prev)
- path.classname = "path_start";
- else
- path.classname = "path_node";
- }
-
- return path;
-}
-
-entity pathlib_astar(vector from,vector to)
-{
- entity path, start, end, open, n, ln;
- float ptime, ftime, ctime;
-
- ptime = gettime(GETTIME_REALTIME);
- pathlib_starttime = ptime;
-
- pathlib_cleanup();
-
- // Select water<->land capable node make/link
- pathlib_makenode = pathlib_makenode_adaptive;
- // Select XYZ cost estimate
- //pathlib_heuristic = pathlib_h_diagonal3;
- pathlib_heuristic = pathlib_h_diagonal;
- // Select distance + waterfactor cost
- pathlib_cost = pathlib_g_euclidean_water;
- // Select star expander
- pathlib_expandnode = pathlib_expandnode_star;
- // Select walk simulation movement test
- pathlib_movenode = pathlib_walknode;
- // Filter final nodes by direction
- buildpath_nodefilter = buildpath_nodefilter_directional;
- // Filter tiles with cross pattern
- tile_check = tile_check_cross;
-
- // If the start is in water we need diffrent settings
- if(inwater(from))
- {
- // Select volumetric node expaner
- pathlib_expandnode = pathlib_expandnode_box;
-
- // Water movement test
- pathlib_movenode = pathlib_swimnode;
- }
-
- if not(openlist)
- openlist = spawn();
-
- if not(closedlist)
- closedlist = spawn();
-
- pathlib_closed_cnt = 0;
- pathlib_open_cnt = 0;
- pathlib_made_cnt = 0;
- pathlib_merge_cnt = 0;
- pathlib_searched_cnt = 0;
- pathlib_bestopen_seached = 0;
- pathlib_bestcash_hits = 0;
- pathlib_bestcash_saved = 0;
-
- pathlib_gridsize = 128;
- pathlib_movecost = pathlib_gridsize;
- pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
- pathlib_movecost_waterfactor = 1;
- pathlib_foundgoal = 0;
-
- movenode_boxmax = self.maxs * 1.25;
- movenode_boxmin = self.mins * 1.25;
-
- movenode_stepsize = 32;
-
- tile_check_size = 65;
- tile_check_up = '0 0 128';
- tile_check_down = '0 0 128';
-
- movenode_stepup = '0 0 36';
- movenode_maxdrop = '0 0 128';
- movenode_boxup = '0 0 72';
-
- from_x = fsnap(from_x,pathlib_gridsize);
- from_y = fsnap(from_y,pathlib_gridsize);
-
- to_x = fsnap(to_x,pathlib_gridsize);
- to_y = fsnap(to_y,pathlib_gridsize);
-
- dprint("AStar init\n");
- path = pathlib_mknode(from,world);
- pathlib_close_node(path,to);
- if(pathlib_foundgoal)
- {
- dprint("AStar: Goal found on first node!\n");
-
- open = spawn();
- open.owner = open;
- open.classname = "path_end";
- setorigin(open,path.origin);
-
- pathlib_cleanup();
-
- return open;
- }
-
- if(pathlib_expandnode(path,from,to) <= 0)
- {
- dprint("AStar path fail.\n");
- pathlib_cleanup();
-
- return world;
- }
-
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode_star(n,from,to);
-
- while(pathlib_open_cnt)
- {
- if((gettime(GETTIME_REALTIME) - pathlib_starttime) > pathlib_maxtime)
- {
- dprint("Path took to long to compute!\n");
- dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
- dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
- dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
- dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
-
- pathlib_cleanup();
- return world;
- }
-
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
-
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode(n,from,to);
-
- if(pathlib_foundgoal)
- {
- dprint("Target found. Rebuilding and filtering path...\n");
- ftime = gettime(GETTIME_REALTIME);
- ptime = ftime - ptime;
-
- start = path_build(world,path.origin,world,world);
- end = path_build(world,goal_node.origin,world,start);
- ln = end;
-
- open = goal_node;
- for(open = goal_node; open.path_prev != path; open = open.path_prev)
- {
- n = path_build(ln,open.origin,open.path_prev,start);
- ln.path_prev = n;
- ln = n;
- }
- start.path_next = n;
- n.path_prev = start;
- ftime = gettime(GETTIME_REALTIME) - ftime;
-
- ctime = gettime(GETTIME_REALTIME);
- pathlib_cleanup();
- ctime = gettime(GETTIME_REALTIME) - ctime;
-
-
-#ifdef DEBUGPATHING
- pathlib_showpath2(start);
-
- dprint("Time used - pathfinding: ", ftos(ptime),"\n");
- dprint("Time used - rebuild & filter: ", ftos(ftime),"\n");
- dprint("Time used - cleanup: ", ftos(ctime),"\n");
- dprint("Time used - total: ", ftos(ptime + ftime + ctime),"\n");
- dprint("Time used - # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_ticrate)),"\n\n");
- dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
- dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
- dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
- dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
- dprint("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n");
- dprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
- dprint("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n");
- dprint("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n");
- dprint("AStar done.\n");
-#endif
- return start;
- }
- }
-
- dprint("A* Faild to find a path! Try a smaller gridsize.\n");
-
- pathlib_cleanup();
-
- return world;
-}
+void pathlib_deletepath(entity start)
+{
+ entity e;
+
+ e = findchainentity(owner, start);
+ while(e)
+ {
+ e.think = SUB_Remove;
+ e.nextthink = time;
+ e = e.chain;
+ }
+}
+
+//#define PATHLIB_NODEEXPIRE 0.05
+#define PATHLIB_NODEEXPIRE 20
+
+void dumpnode(entity n)
+{
+ n.is_path_node = FALSE;
+ n.think = SUB_Remove;
+ n.nextthink = time;
+}
+
+entity pathlib_mknode(vector where,entity parent)
+{
+ entity node;
+
+ node = pathlib_nodeatpoint(where);
+ if(node)
+ {
+ mark_error(where,60);
+ return node;
+ }
+
+ node = spawn();
+
+ node.think = SUB_Remove;
+ node.nextthink = time + PATHLIB_NODEEXPIRE;
+ node.is_path_node = TRUE;
+ node.owner = openlist;
+ node.path_prev = parent;
+
+ setmodel(node,"models/pathlib/square.md3");
+ setsize(node,'0 0 0','0 0 0');
+ node.colormod = randomvec() * 2;
+ node.alpha = 0.25;
+ node.scale = pathlib_gridsize / 512.001;
+
+ //pathlib_showsquare2(node,'1 1 1',0);//(node.medium & CONTENT_EMPTY));
+ setorigin(node, where);
+ node.medium = pointcontents(where);
+
+ mark_info(where,60);
+ //pathlib_showsquare(where,1,30);
+
+
+ ++pathlib_made_cnt;
+ ++pathlib_open_cnt;
+
+ return node;
+}
+
+float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
+{
+ entity node;
+ float h,g,f,doedge;
+ vector where;
+
+ ++pathlib_searched_cnt;
+
+ if(inwater(parent.origin))
+ {
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ else
+ {
+ if(inwater(to))
+ {
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_walknode;
+ }
+ else
+ {
+ //if(edge_check(parent.origin))
+ // return 0;
+
+ pathlib_expandnode = pathlib_expandnode_star;
+ pathlib_movenode = pathlib_walknode;
+ doedge = 1;
+ }
+ }
+
+ node = pathlib_nodeatpoint(to);
+ if(node)
+ {
+ ++pathlib_merge_cnt;
+
+ if(node.owner == openlist)
+ {
+ h = pathlib_heuristic(node.origin,goal);
+ g = pathlib_cost(parent,node.origin,cost);
+ f = g + h;
+
+ if(node.pathlib_node_g > g)
+ {
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+
+ node.path_prev = parent;
+ }
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+ }
+
+ return 1;
+ }
+
+ where = pathlib_movenode(parent.origin,to,0);
+ if not(pathlib_movenode_goodnode)
+ return 0;
+
+ if(pathlib_nodeatpoint(where))
+ {
+ dprint("NAP WHERE :",vtos(where),"\n");
+ dprint("not NAP TO:",vtos(to),"\n");
+ dprint("NAP-NNAP:",ftos(vlen(to-where)),"\n\n");
+ return 0;
+ }
+
+ if(doedge)
+ if not (tile_check(where))
+ return 0;
+
+ h = pathlib_heuristic(where,goal);
+ g = pathlib_cost(parent,where,cost);
+ f = g + h;
+
+
+ /*
+ node = findradius(where,pathlib_gridsize * 0.5);
+ while(node)
+ {
+ if(node.is_path_node == TRUE)
+ {
+ ++pathlib_merge_cnt;
+ if(node.owner == openlist)
+ {
+ if(node.pathlib_node_g > g)
+ {
+ //pathlib_movenode(where,node.origin,0);
+ //if(pathlib_movenode_goodnode)
+ //{
+ //mark_error(node.origin + '0 0 128',30);
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+ node.path_prev = parent;
+ //}
+ }
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+ }
+
+ return 1;
+ }
+ node = node.chain;
+ }
+ */
+
+ node = pathlib_mknode(where,parent);
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+
+ return 1;
+}
+
+entity pathlib_getbestopen()
+{
+ entity node;
+ entity bestnode;
+
+ if(best_open_node)
+ {
+ ++pathlib_bestcash_hits;
+ pathlib_bestcash_saved += pathlib_open_cnt;
+
+ return best_open_node;
+ }
+
+ node = findchainentity(owner,openlist);
+ if(!node)
+ return world;
+
+ bestnode = node;
+ while(node)
+ {
+ ++pathlib_bestopen_seached;
+ if(node.pathlib_node_f < bestnode.pathlib_node_f)
+ bestnode = node;
+
+ node = node.chain;
+ }
+
+ return bestnode;
+}
+
+void pathlib_close_node(entity node,vector goal)
+{
+
+ if(node.owner == closedlist)
+ {
+ dprint("Pathlib: Tried to close a closed node!\n");
+ return;
+ }
+
+ if(node == best_open_node)
+ best_open_node = world;
+
+ ++pathlib_closed_cnt;
+ --pathlib_open_cnt;
+
+ node.owner = closedlist;
+
+ if(vlen(node.origin - goal) <= pathlib_gridsize)
+ {
+ vector goalmove;
+
+ goalmove = pathlib_walknode(node.origin,goal,1);
+ if(pathlib_movenode_goodnode)
+ {
+ goal_node = node;
+ pathlib_foundgoal = TRUE;
+ }
+ }
+}
+
+void pathlib_cleanup()
+{
+ best_open_node = world;
+
+ //return;
+
+ entity node;
+
+ node = findfloat(world,is_path_node, TRUE);
+ while(node)
+ {
+ /*
+ node.owner = openlist;
+ node.pathlib_node_g = 0;
+ node.pathlib_node_h = 0;
+ node.pathlib_node_f = 0;
+ node.path_prev = world;
+ */
+
+ dumpnode(node);
+ node = findfloat(node,is_path_node, TRUE);
+ }
+
+ if(openlist)
+ remove(openlist);
+
+ if(closedlist)
+ remove(closedlist);
+
+ openlist = world;
+ closedlist = world;
+
+}
+
+float Cosine_Interpolate(float a, float b, float x)
+{
+ float ft,f;
+
+ ft = x * 3.1415927;
+ f = (1 - cos(ft)) * 0.5;
+
+ return a*(1-f) + b*f;
+}
+
+float buildpath_nodefilter_directional(vector n,vector c,vector p)
+{
+ vector d1,d2;
+
+ d2 = normalize(p - c);
+ d1 = normalize(c - n);
+
+ if(vlen(d1-d2) < 0.25)
+ {
+ //mark_error(c,30);
+ return 1;
+ }
+ //mark_info(c,30);
+ return 0;
+}
+
+float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
+{
+ pathlib_walknode(p,n,1);
+ if(pathlib_movenode_goodnode)
+ return 1;
+
+ return 0;
+}
+
+entity path_build(entity next, vector where, entity prev, entity start)
+{
+ entity path;
+
+ if(prev && next)
+ if(buildpath_nodefilter)
+ if(buildpath_nodefilter(next.origin,where,prev.origin))
+ return next;
+
+
+ path = spawn();
+ path.owner = start;
+ path.path_next = next;
+
+ setorigin(path,where);
+
+ if(!next)
+ path.classname = "path_end";
+ else
+ {
+ if(!prev)
+ path.classname = "path_start";
+ else
+ path.classname = "path_node";
+ }
+
+ return path;
+}
+
+entity pathlib_astar(vector from,vector to)
+{
+ entity path, start, end, open, n, ln;
+ float ptime, ftime, ctime;
+
+ ptime = gettime(GETTIME_REALTIME);
+ pathlib_starttime = ptime;
+
+ pathlib_cleanup();
+
+ // Select water<->land capable node make/link
+ pathlib_makenode = pathlib_makenode_adaptive;
+ // Select XYZ cost estimate
+ //pathlib_heuristic = pathlib_h_diagonal3;
+ pathlib_heuristic = pathlib_h_diagonal;
+ // Select distance + waterfactor cost
+ pathlib_cost = pathlib_g_euclidean_water;
+ // Select star expander
+ pathlib_expandnode = pathlib_expandnode_star;
+ // Select walk simulation movement test
+ pathlib_movenode = pathlib_walknode;
+ // Filter final nodes by direction
+ buildpath_nodefilter = buildpath_nodefilter_directional;
+ // Filter tiles with cross pattern
+ tile_check = tile_check_cross;
+
+ // If the start is in water we need diffrent settings
+ if(inwater(from))
+ {
+ // Select volumetric node expaner
+ pathlib_expandnode = pathlib_expandnode_box;
+
+ // Water movement test
+ pathlib_movenode = pathlib_swimnode;
+ }
+
+ if not(openlist)
+ openlist = spawn();
+
+ if not(closedlist)
+ closedlist = spawn();
+
+ pathlib_closed_cnt = 0;
+ pathlib_open_cnt = 0;
+ pathlib_made_cnt = 0;
+ pathlib_merge_cnt = 0;
+ pathlib_searched_cnt = 0;
+ pathlib_bestopen_seached = 0;
+ pathlib_bestcash_hits = 0;
+ pathlib_bestcash_saved = 0;
+
+ pathlib_gridsize = 128;
+ pathlib_movecost = pathlib_gridsize;
+ pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
+ pathlib_movecost_waterfactor = 1;
+ pathlib_foundgoal = 0;
+
+ movenode_boxmax = self.maxs * 1.25;
+ movenode_boxmin = self.mins * 1.25;
+
+ movenode_stepsize = 32;
+
+ tile_check_size = 65;
+ tile_check_up = '0 0 128';
+ tile_check_down = '0 0 128';
+
+ movenode_stepup = '0 0 36';
+ movenode_maxdrop = '0 0 128';
+ movenode_boxup = '0 0 72';
+
+ from_x = fsnap(from_x,pathlib_gridsize);
+ from_y = fsnap(from_y,pathlib_gridsize);
+
+ to_x = fsnap(to_x,pathlib_gridsize);
+ to_y = fsnap(to_y,pathlib_gridsize);
+
+ dprint("AStar init\n");
+ path = pathlib_mknode(from,world);
+ pathlib_close_node(path,to);
+ if(pathlib_foundgoal)
+ {
+ dprint("AStar: Goal found on first node!\n");
+
+ open = spawn();
+ open.owner = open;
+ open.classname = "path_end";
+ setorigin(open,path.origin);
+
+ pathlib_cleanup();
+
+ return open;
+ }
+
+ if(pathlib_expandnode(path,from,to) <= 0)
+ {
+ dprint("AStar path fail.\n");
+ pathlib_cleanup();
+
+ return world;
+ }
+
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode_star(n,from,to);
+
+ while(pathlib_open_cnt)
+ {
+ if((gettime(GETTIME_REALTIME) - pathlib_starttime) > pathlib_maxtime)
+ {
+ dprint("Path took to long to compute!\n");
+ dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
+ dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
+ dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
+ dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
+
+ pathlib_cleanup();
+ return world;
+ }
+
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode(n,from,to);
+
+ if(pathlib_foundgoal)
+ {
+ dprint("Target found. Rebuilding and filtering path...\n");
+ ftime = gettime(GETTIME_REALTIME);
+ ptime = ftime - ptime;
+
+ start = path_build(world,path.origin,world,world);
+ end = path_build(world,goal_node.origin,world,start);
+ ln = end;
+
+ open = goal_node;
+ for(open = goal_node; open.path_prev != path; open = open.path_prev)
+ {
+ n = path_build(ln,open.origin,open.path_prev,start);
+ ln.path_prev = n;
+ ln = n;
+ }
+ start.path_next = n;
+ n.path_prev = start;
+ ftime = gettime(GETTIME_REALTIME) - ftime;
+
+ ctime = gettime(GETTIME_REALTIME);
+ pathlib_cleanup();
+ ctime = gettime(GETTIME_REALTIME) - ctime;
+
+
+#ifdef DEBUGPATHING
+ pathlib_showpath2(start);
+
+ dprint("Time used - pathfinding: ", ftos(ptime),"\n");
+ dprint("Time used - rebuild & filter: ", ftos(ftime),"\n");
+ dprint("Time used - cleanup: ", ftos(ctime),"\n");
+ dprint("Time used - total: ", ftos(ptime + ftime + ctime),"\n");
+ dprint("Time used - # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_ticrate)),"\n\n");
+ dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
+ dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
+ dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
+ dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
+ dprint("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n");
+ dprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
+ dprint("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n");
+ dprint("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n");
+ dprint("AStar done.\n");
+#endif
+ return start;
+ }
+ }
+
+ dprint("A* Faild to find a path! Try a smaller gridsize.\n");
+
+ pathlib_cleanup();
+
+ return world;
+}
Property changes on: trunk/data/qcsrc/server/pathlib/main.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/movenode.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/movenode.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/movenode.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,126 +1,126 @@
-vector pathlib_wateroutnode(vector start,vector end)
-{
- vector surface;
-
- pathlib_movenode_goodnode = 0;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
- end = trace_endpos;
-
- if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
- return end;
-
- for(surface = start ; surface_z < (end_z + 32); ++surface_z)
- {
- if(pointcontents(surface) == CONTENT_EMPTY)
- break;
- }
-
- if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
- return end;
-
- tracebox(start + '0 0 64', movenode_boxmin,movenode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- if(fabs(surface_z - end_z) > 32)
- pathlib_movenode_goodnode = 0;
-
- return end;
-}
-
-vector pathlib_swimnode(vector start,vector end)
-{
- pathlib_movenode_goodnode = 0;
-
- if(pointcontents(start) != CONTENT_WATER)
- return end;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- if(pointcontents(end) == CONTENT_EMPTY)
- return pathlib_wateroutnode( start, end);
-
- tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_flynode(vector start,vector end)
-{
- pathlib_movenode_goodnode = 0;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_walknode(vector start,vector end,float doedge)
-{
- vector direction,point,last_point,s,e;
- float steps, distance, i;
-
- pathlib_movenode_goodnode = 0;
-
- end_x = fsnap(end_x,pathlib_gridsize);
- end_y = fsnap(end_y,pathlib_gridsize);
- start_x = fsnap(start_x,pathlib_gridsize);
- start_y = fsnap(start_y,pathlib_gridsize);
-
- // Find the floor
- traceline(start + movenode_stepup, start - movenode_maxdrop,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- start = trace_endpos;
-
- // Find the direcion, without Z
- s = start; e = end;
- //e_z = 0; s_z = 0;
- direction = normalize(e - s);
-
- distance = vlen(start - end);
- steps = rint(distance / movenode_stepsize);
-
- last_point = start;
- for(i = 1; i < steps; ++i)
- {
- point = last_point + (direction * movenode_stepsize);
- traceline(point + movenode_stepup,point - movenode_maxdrop,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- last_point = trace_endpos;
- }
-
- point = last_point + (direction * movenode_stepsize);
- point_x = fsnap(point_x,pathlib_gridsize);
- point_y = fsnap(point_y,pathlib_gridsize);
-
- //dprint("end_x: ",ftos(end_x), " end_y: ",ftos(end_y),"\n");
- //dprint("point_x:",ftos(point_x)," point_y:",ftos(point_y),"\n\n");
-
- traceline(point + movenode_stepup, point - movenode_maxdrop,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- last_point = trace_endpos;
-
- tracebox(start + movenode_boxup, movenode_boxmin,movenode_boxmax, last_point + movenode_boxup, MOVE_WORLDONLY, self);
- if(trace_fraction != 1.0)
- return trace_endpos;
-
- pathlib_movenode_goodnode = 1;
- return last_point;
-}
+vector pathlib_wateroutnode(vector start,vector end)
+{
+ vector surface;
+
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
+ end = trace_endpos;
+
+ if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
+ return end;
+
+ for(surface = start ; surface_z < (end_z + 32); ++surface_z)
+ {
+ if(pointcontents(surface) == CONTENT_EMPTY)
+ break;
+ }
+
+ if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
+ return end;
+
+ tracebox(start + '0 0 64', movenode_boxmin,movenode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ if(fabs(surface_z - end_z) > 32)
+ pathlib_movenode_goodnode = 0;
+
+ return end;
+}
+
+vector pathlib_swimnode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ if(pointcontents(start) != CONTENT_WATER)
+ return end;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ if(pointcontents(end) == CONTENT_EMPTY)
+ return pathlib_wateroutnode( start, end);
+
+ tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_flynode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_walknode(vector start,vector end,float doedge)
+{
+ vector direction,point,last_point,s,e;
+ float steps, distance, i;
+
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x,pathlib_gridsize);
+ end_y = fsnap(end_y,pathlib_gridsize);
+ start_x = fsnap(start_x,pathlib_gridsize);
+ start_y = fsnap(start_y,pathlib_gridsize);
+
+ // Find the floor
+ traceline(start + movenode_stepup, start - movenode_maxdrop,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ start = trace_endpos;
+
+ // Find the direcion, without Z
+ s = start; e = end;
+ //e_z = 0; s_z = 0;
+ direction = normalize(e - s);
+
+ distance = vlen(start - end);
+ steps = rint(distance / movenode_stepsize);
+
+ last_point = start;
+ for(i = 1; i < steps; ++i)
+ {
+ point = last_point + (direction * movenode_stepsize);
+ traceline(point + movenode_stepup,point - movenode_maxdrop,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ last_point = trace_endpos;
+ }
+
+ point = last_point + (direction * movenode_stepsize);
+ point_x = fsnap(point_x,pathlib_gridsize);
+ point_y = fsnap(point_y,pathlib_gridsize);
+
+ //dprint("end_x: ",ftos(end_x), " end_y: ",ftos(end_y),"\n");
+ //dprint("point_x:",ftos(point_x)," point_y:",ftos(point_y),"\n\n");
+
+ traceline(point + movenode_stepup, point - movenode_maxdrop,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ last_point = trace_endpos;
+
+ tracebox(start + movenode_boxup, movenode_boxmin,movenode_boxmax, last_point + movenode_boxup, MOVE_WORLDONLY, self);
+ if(trace_fraction != 1.0)
+ return trace_endpos;
+
+ pathlib_movenode_goodnode = 1;
+ return last_point;
+}
Property changes on: trunk/data/qcsrc/server/pathlib/movenode.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/pathlib.qh
===================================================================
--- trunk/data/qcsrc/server/pathlib/pathlib.qh 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/pathlib.qh 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,99 +1,99 @@
-.entity path_next;
-.entity path_prev;
-
-#define inwater(point) (pointcontents(point) == CONTENT_WATER)
-#define medium spawnshieldtime
-
-#define PLIB_FORWARD '0 1 0'
-//#define PLIB_BACK '0 -1 0'
-#define PLIB_RIGHT '1 0 0'
-//#define PLIB_LEFT '-1 0 0'
-
-#define DEBUGPATHING
-#ifdef DEBUGPATHING
-void pathlib_showpath(entity start);
-void pathlib_showpath2(entity path);
-#endif
-
-entity openlist;
-entity closedlist;
-entity goal_node;
-
-.float is_path_node;
-.float pathlib_node_g;
-.float pathlib_node_h;
-.float pathlib_node_f;
-
-float pathlib_open_cnt;
-float pathlib_closed_cnt;
-float pathlib_made_cnt;
-float pathlib_merge_cnt;
-float pathlib_searched_cnt;
-float pathlib_bestopen_seached;
-float pathlib_bestcash_hits;
-float pathlib_bestcash_saved;
-float pathlib_gridsize;
-float pathlib_movecost;
-float pathlib_movecost_diag;
-float pathlib_movecost_waterfactor;
-float pathlib_foundgoal;
-
-float pathlib_starttime;
-#define pathlib_maxtime 5
-
-entity best_open_node;
-
-vector tile_check_up;
-vector tile_check_down;
-float tile_check_size;
-float tile_check_cross(vector where);
-float tile_check_plus(vector where);
-float tile_check_star(vector where);
-var float tile_check(vector where);
-
-float movenode_stepsize;
-vector movenode_stepup;
-vector movenode_maxdrop;
-vector movenode_boxup;
-vector movenode_boxmax;
-vector movenode_boxmin;
-float pathlib_movenode_goodnode;
-
-vector pathlib_wateroutnode(vector start, vector end);
-vector pathlib_swimnode(vector start, vector end);
-vector pathlib_flynode(vector start, vector end);
-vector pathlib_walknode(vector start, vector end, float doedge);
-var vector pathlib_movenode(vector start, vector end, float doedge);
-
-float pathlib_expandnode_star(entity node, vector start, vector goal);
-float pathlib_expandnode_box(entity node, vector start, vector goal);
-float pathlib_expandnode_octagon(entity node, vector start, vector goal);
-var float pathlib_expandnode(entity node, vector start, vector goal);
-
-float pathlib_g_static(entity parent, vector to, float static_cost);
-float pathlib_g_static_water(entity parent, vector to, float static_cost);
-float pathlib_g_euclidean(entity parent, vector to, float static_cost);
-float pathlib_g_euclidean_water(entity parent, vector to, float static_cost);
-var float pathlib_cost(entity parent, vector to, float static_cost);
-
-float pathlib_h_manhattan(vector a, vector b);
-float pathlib_h_diagonal(vector a, vector b);
-float pathlib_h_euclidean(vector a,vector b);
-float pathlib_h_diagonal2(vector a, vector b);
-float pathlib_h_diagonal3(vector a, vector b);
-float pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
-var float pathlib_heuristic(vector from, vector to);
-
-var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
-var float buildpath_nodefilter(vector n,vector c,vector p);
-
-
-#ifdef DEBUGPATHING
-#include "debug.qc"
-#endif
-
-#include "utility.qc"
-#include "movenode.qc"
-#include "costs.qc"
-#include "expandnode.qc"
-#include "main.qc"
+.entity path_next;
+.entity path_prev;
+
+#define inwater(point) (pointcontents(point) == CONTENT_WATER)
+#define medium spawnshieldtime
+
+#define PLIB_FORWARD '0 1 0'
+//#define PLIB_BACK '0 -1 0'
+#define PLIB_RIGHT '1 0 0'
+//#define PLIB_LEFT '-1 0 0'
+
+#define DEBUGPATHING
+#ifdef DEBUGPATHING
+void pathlib_showpath(entity start);
+void pathlib_showpath2(entity path);
+#endif
+
+entity openlist;
+entity closedlist;
+entity goal_node;
+
+.float is_path_node;
+.float pathlib_node_g;
+.float pathlib_node_h;
+.float pathlib_node_f;
+
+float pathlib_open_cnt;
+float pathlib_closed_cnt;
+float pathlib_made_cnt;
+float pathlib_merge_cnt;
+float pathlib_searched_cnt;
+float pathlib_bestopen_seached;
+float pathlib_bestcash_hits;
+float pathlib_bestcash_saved;
+float pathlib_gridsize;
+float pathlib_movecost;
+float pathlib_movecost_diag;
+float pathlib_movecost_waterfactor;
+float pathlib_foundgoal;
+
+float pathlib_starttime;
+#define pathlib_maxtime 5
+
+entity best_open_node;
+
+vector tile_check_up;
+vector tile_check_down;
+float tile_check_size;
+float tile_check_cross(vector where);
+float tile_check_plus(vector where);
+float tile_check_star(vector where);
+var float tile_check(vector where);
+
+float movenode_stepsize;
+vector movenode_stepup;
+vector movenode_maxdrop;
+vector movenode_boxup;
+vector movenode_boxmax;
+vector movenode_boxmin;
+float pathlib_movenode_goodnode;
+
+vector pathlib_wateroutnode(vector start, vector end);
+vector pathlib_swimnode(vector start, vector end);
+vector pathlib_flynode(vector start, vector end);
+vector pathlib_walknode(vector start, vector end, float doedge);
+var vector pathlib_movenode(vector start, vector end, float doedge);
+
+float pathlib_expandnode_star(entity node, vector start, vector goal);
+float pathlib_expandnode_box(entity node, vector start, vector goal);
+float pathlib_expandnode_octagon(entity node, vector start, vector goal);
+var float pathlib_expandnode(entity node, vector start, vector goal);
+
+float pathlib_g_static(entity parent, vector to, float static_cost);
+float pathlib_g_static_water(entity parent, vector to, float static_cost);
+float pathlib_g_euclidean(entity parent, vector to, float static_cost);
+float pathlib_g_euclidean_water(entity parent, vector to, float static_cost);
+var float pathlib_cost(entity parent, vector to, float static_cost);
+
+float pathlib_h_manhattan(vector a, vector b);
+float pathlib_h_diagonal(vector a, vector b);
+float pathlib_h_euclidean(vector a,vector b);
+float pathlib_h_diagonal2(vector a, vector b);
+float pathlib_h_diagonal3(vector a, vector b);
+float pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
+var float pathlib_heuristic(vector from, vector to);
+
+var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
+var float buildpath_nodefilter(vector n,vector c,vector p);
+
+
+#ifdef DEBUGPATHING
+#include "debug.qc"
+#endif
+
+#include "utility.qc"
+#include "movenode.qc"
+#include "costs.qc"
+#include "expandnode.qc"
+#include "main.qc"
Property changes on: trunk/data/qcsrc/server/pathlib/pathlib.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib/utility.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib/utility.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib/utility.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,162 +1,162 @@
-float fsnap(float val,float fsize)
-{
- return rint(val / fsize) * fsize;
-}
-
-vector vsnap(vector point,float fsize)
-{
- vector vret;
-
- vret_x = rint(point_x / fsize) * fsize;
- vret_y = rint(point_y / fsize) * fsize;
- vret_z = ceil(point_z / fsize) * fsize;
-
- return vret;
-}
-
-float location_isok(vector point, float water_isok, float air_isok)
-{
- float pc,pc2;
-
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
- return 0;
-
- pc = pointcontents(point);
- pc2 = pointcontents(point - '0 0 1');
-
- switch(pc)
- {
- case CONTENT_SOLID:
- break;
-
- case CONTENT_SLIME:
- break;
-
- case CONTENT_LAVA:
- break;
-
- case CONTENT_SKY:
- break;
-
- case CONTENT_EMPTY:
- if (pc2 == CONTENT_SOLID)
- return 1;
-
- if (pc2 == CONTENT_EMPTY)
- if(air_isok)
- return 1;
-
- if (pc2 == CONTENT_WATER)
- if(water_isok)
- return 1;
-
- break;
-
- case CONTENT_WATER:
- if (water_isok)
- return 1;
-
- break;
- }
-
- return 0;
-}
-
-entity pathlib_nodeatpoint(vector where)
-{
- entity node;
-
- ++pathlib_searched_cnt;
-
- where_x = fsnap(where_x,pathlib_gridsize);
- where_y = fsnap(where_y,pathlib_gridsize);
-
- node = findradius(where,pathlib_gridsize * 0.5);
- while(node)
- {
- if(node.is_path_node == TRUE)
- return node;
-
- node = node.chain;
- }
-
- return world;
-}
-
-float tile_check_cross(vector where)
-{
- vector p,f,r;
-
- f = PLIB_FORWARD * tile_check_size;
- r = PLIB_RIGHT * tile_check_size;
-
- // forward-right
- p = where + f + r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- // Forward-left
- p = where + f - r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- // Back-right
- p = where - f + r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- //Back-left
- p = where - f - r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- return 1;
-}
-
-float tile_check_plus(vector where)
-{
- vector p,f,r;
-
- f = PLIB_FORWARD * tile_check_size;
- r = PLIB_RIGHT * tile_check_size;
-
- // forward
- p = where + f;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- //left
- p = where - r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
-
- // Right
- p = where + r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- //Back
- p = where - f;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
- return 0;
-
- return 1;
-}
-
-float tile_check_star(vector where)
-{
- if(tile_check_plus(where))
- return tile_check_cross(where);
-
- return 0;
-}
-
+float fsnap(float val,float fsize)
+{
+ return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+ vector vret;
+
+ vret_x = rint(point_x / fsize) * fsize;
+ vret_y = rint(point_y / fsize) * fsize;
+ vret_z = ceil(point_z / fsize) * fsize;
+
+ return vret;
+}
+
+float location_isok(vector point, float water_isok, float air_isok)
+{
+ float pc,pc2;
+
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ return 0;
+
+ pc = pointcontents(point);
+ pc2 = pointcontents(point - '0 0 1');
+
+ switch(pc)
+ {
+ case CONTENT_SOLID:
+ break;
+
+ case CONTENT_SLIME:
+ break;
+
+ case CONTENT_LAVA:
+ break;
+
+ case CONTENT_SKY:
+ break;
+
+ case CONTENT_EMPTY:
+ if (pc2 == CONTENT_SOLID)
+ return 1;
+
+ if (pc2 == CONTENT_EMPTY)
+ if(air_isok)
+ return 1;
+
+ if (pc2 == CONTENT_WATER)
+ if(water_isok)
+ return 1;
+
+ break;
+
+ case CONTENT_WATER:
+ if (water_isok)
+ return 1;
+
+ break;
+ }
+
+ return 0;
+}
+
+entity pathlib_nodeatpoint(vector where)
+{
+ entity node;
+
+ ++pathlib_searched_cnt;
+
+ where_x = fsnap(where_x,pathlib_gridsize);
+ where_y = fsnap(where_y,pathlib_gridsize);
+
+ node = findradius(where,pathlib_gridsize * 0.5);
+ while(node)
+ {
+ if(node.is_path_node == TRUE)
+ return node;
+
+ node = node.chain;
+ }
+
+ return world;
+}
+
+float tile_check_cross(vector where)
+{
+ vector p,f,r;
+
+ f = PLIB_FORWARD * tile_check_size;
+ r = PLIB_RIGHT * tile_check_size;
+
+ // forward-right
+ p = where + f + r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ // Forward-left
+ p = where + f - r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ // Back-right
+ p = where - f + r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ //Back-left
+ p = where - f - r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ return 1;
+}
+
+float tile_check_plus(vector where)
+{
+ vector p,f,r;
+
+ f = PLIB_FORWARD * tile_check_size;
+ r = PLIB_RIGHT * tile_check_size;
+
+ // forward
+ p = where + f;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ //left
+ p = where - r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+
+ // Right
+ p = where + r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ //Back
+ p = where - f;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if not (location_isok(trace_endpos,1,0))
+ return 0;
+
+ return 1;
+}
+
+float tile_check_star(vector where)
+{
+ if(tile_check_plus(where))
+ return tile_check_cross(where);
+
+ return 0;
+}
+
Property changes on: trunk/data/qcsrc/server/pathlib/utility.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/pathlib.qc
===================================================================
--- trunk/data/qcsrc/server/pathlib.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/pathlib.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,1047 +1,1047 @@
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
- #define path_next swampslug
- #define path_prev lasertarget
-#else
- .entity path_next;
- .entity path_prev;
-#endif
-
-#define medium spawnshieldtime
-
-//#define DEBUGPATHING
-
-entity openlist;
-entity closedlist;
-entity scraplist;
-
-.float pathlib_node_g;
-.float pathlib_node_h;
-.float pathlib_node_f;
-
-float pathlib_open_cnt;
-float pathlib_closed_cnt;
-float pathlib_made_cnt;
-float pathlib_merge_cnt;
-float pathlib_recycle_cnt;
-float pathlib_searched_cnt;
-
-#ifdef DEBUGPATHING
-
-#endif
-
-float pathlib_bestopen_seached;
-float pathlib_bestcash_hits;
-float pathlib_bestcash_saved;
-
-float pathlib_gridsize;
-
-float pathlib_movecost;
-float pathlib_movecost_diag;
-float pathlib_movecost_waterfactor;
-
-float pathlib_edge_check_size;
-
-float pathlib_foundgoal;
-entity goal_node;
-
-entity best_open_node;
-.float is_path_node;
-
-
-#ifdef DEBUGPATHING
-float edge_show(vector point,float fsize);
-void mark_error(vector where,float lifetime);
-void mark_info(vector where,float lifetime);
-entity mark_misc(vector where,float lifetime);
-
-void pathlib_showpath(entity start)
-{
- entity e;
- e = start;
- while(e.path_next)
- {
- te_lightning1(e,e.origin,e.path_next.origin);
- e = e.path_next;
- }
-}
-
-void path_dbg_think()
-{
- pathlib_showpath(self);
- self.nextthink = time + 1;
-}
-
-void __showpath2_think()
-{
- mark_info(self.origin,1);
- if(self.path_next)
- {
- self.path_next.think = __showpath2_think;
- self.path_next.nextthink = time + 0.15;
- }
- else
- {
- self.owner.think = __showpath2_think;
- self.owner.nextthink = time + 0.15;
- }
-}
-
-void pathlib_showpath2(entity path)
-{
- path.think = __showpath2_think;
- path.nextthink = time;
-}
-
-#endif
-
-void pathlib_deletepath(entity start)
-{
- entity e;
-
- e = findchainentity(owner, start);
- while(e)
- {
- e.think = SUB_Remove;
- e.nextthink = time;
- e = e.chain;
- }
-}
-
-float fsnap(float val,float fsize)
-{
- return rint(val / fsize) * fsize;
-}
-
-vector vsnap(vector point,float fsize)
-{
- vector vret;
-
- vret_x = rint(point_x / fsize) * fsize;
- vret_y = rint(point_y / fsize) * fsize;
- vret_z = ceil(point_z / fsize) * fsize;
-
- return vret;
-}
-
-float walknode_stepsize;
-vector walknode_stepup;
-vector walknode_maxdrop;
-vector walknode_boxup;
-vector walknode_boxmax;
-vector walknode_boxmin;
-float pathlib_movenode_goodnode;
-
-float floor_ok(vector point)
-{
- float pc;
-
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
- return 0;
-
- pc = pointcontents(point);
-
- switch(pc)
- {
- case CONTENT_SOLID:
- case CONTENT_SLIME:
- case CONTENT_LAVA:
- case CONTENT_SKY:
- return 0;
- case CONTENT_EMPTY:
- if not (pointcontents(point - '0 0 1') == CONTENT_SOLID)
- return 0;
- break;
- case CONTENT_WATER:
- return 1;
- }
- if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
- return 1;
-
- return 0;
-}
-
-#define inwater(point) (pointcontents(point) == CONTENT_WATER)
-/*
-float inwater(vector point)
-{
- if(pointcontents(point) == CONTENT_WATER)
- return 1;
- return 0;
-}
-*/
-
-#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if not(floor_ok(trace_endpos)) return 1
-float edge_check(vector point,float fsize)
-{
- vector z_up,z_down;
-
- z_up = '0 0 1' * fsize;
- z_down = '0 0 1' * fsize;
-
- _pcheck(point + ('1 1 0' * fsize));
- _pcheck(point + ('1 -1 0' * fsize));
- _pcheck(point + ('1 0 0' * fsize));
-
- _pcheck(point + ('0 1 0' * fsize));
- _pcheck(point + ('0 -1 0' * fsize));
-
- _pcheck(point + ('-1 0 0' * fsize));
- _pcheck(point + ('-1 1 0' * fsize));
- _pcheck(point + ('-1 -1 0' * fsize));
-
- return 0;
-}
-
-#ifdef DEBUGPATHING
-#define _pshow(p) mark_error(p,10)
-float edge_show(vector point,float fsize)
-{
-
- _pshow(point + ('1 1 0' * fsize));
- _pshow(point + ('1 -1 0' * fsize));
- _pshow(point + ('1 0 0' * fsize));
-
- _pshow(point + ('0 1 0' * fsize));
- _pshow(point + ('0 -1 0' * fsize));
-
- _pshow(point + ('-1 0 0' * fsize));
- _pshow(point + ('-1 1 0' * fsize));
- _pshow(point + ('-1 -1 0' * fsize));
-
- return 0;
-}
-#endif
-
-var vector pathlib_movenode(vector start,vector end,float doedge);
-vector pathlib_wateroutnode(vector start,vector end)
-{
- vector surface;
-
- pathlib_movenode_goodnode = 0;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
- end = trace_endpos;
-
- if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
- return end;
-
- for(surface = start ; surface_z < (end_z + 32); ++surface_z)
- {
- if(pointcontents(surface) == CONTENT_EMPTY)
- break;
- }
-
- if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
- return end;
-
- tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- if(fabs(surface_z - end_z) > 32)
- pathlib_movenode_goodnode = 0;
-
- return end;
-}
-
-vector pathlib_swimnode(vector start,vector end)
-{
- pathlib_movenode_goodnode = 0;
-
- if(pointcontents(start) != CONTENT_WATER)
- return end;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- if(pointcontents(end) == CONTENT_EMPTY)
- return pathlib_wateroutnode( start, end);
-
- tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_flynode(vector start,vector end)
-{
- pathlib_movenode_goodnode = 0;
-
- end_x = fsnap(end_x, pathlib_gridsize);
- end_y = fsnap(end_y, pathlib_gridsize);
-
- tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
- if(trace_fraction == 1)
- pathlib_movenode_goodnode = 1;
-
- return end;
-}
-
-vector pathlib_walknode(vector start,vector end,float doedge)
-{
- vector direction,point,last_point,s,e;
- float steps, distance, i,laststep;
-
- pathlib_movenode_goodnode = 0;
-
- s = start;
- e = end;
- e_z = 0;
- s_z = 0;
- direction = normalize(s - e);
-
- distance = vlen(start - end);
- laststep = distance / walknode_stepsize;
- steps = floor(laststep);
- laststep = laststep - steps;
-
- point = start;
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
-
- traceline(s, e,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- if (floor_ok(trace_endpos) == 0)
- return trace_endpos;
-
- last_point = trace_endpos;
-
- for(i = 0; i < steps; ++i)
- {
- point = last_point + direction * walknode_stepsize;
-
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
- traceline(s, e,MOVE_WORLDONLY,self);
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- point = trace_endpos;
- if not(floor_ok(trace_endpos))
- return trace_endpos;
-
- tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
- if(trace_fraction != 1.0)
- return trace_endpos;
-
- if(doedge)
- if(edge_check(point,pathlib_edge_check_size))
- return trace_endpos;
-
- last_point = point;
- }
-
- point = last_point + direction * walknode_stepsize * laststep;
-
- point_x = fsnap(point_x, pathlib_gridsize);
- point_y = fsnap(point_y, pathlib_gridsize);
-
- s = point + walknode_stepup;
- e = point - walknode_maxdrop;
- traceline(s, e,MOVE_WORLDONLY,self);
-
- if(trace_fraction == 1.0)
- return trace_endpos;
-
- point = trace_endpos;
-
- if not(floor_ok(trace_endpos))
- return trace_endpos;
-
- tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
- if(trace_fraction != 1.0)
- return trace_endpos;
-
- pathlib_movenode_goodnode = 1;
- return point;
-}
-
-var float pathlib_cost(entity parent,vector to, float static_cost);
-float pathlib_g_static(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_static_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_euclidean(entity parent,vector to, float static_cost)
-{
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
-{
- if(inwater(to))
- return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
- else
- return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-
-var float(vector from,vector to) pathlib_heuristic;
-
-/**
- Manhattan Menas we expect to move up,down left or right
- No diagonal moves espected. (like moving bewteen city blocks)
-**/
-float pathlib_h_manhattan(vector a,vector b)
-{
- //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
-
- float h;
- h = fabs(a_x - b_x);
- h += fabs(a_y - b_y);
- h *= pathlib_gridsize;
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves
- to have teh same cost.
-**/
-float pathlib_h_diagonal(vector a,vector b)
-{
- //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
- float h,x,y;
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
- h = pathlib_movecost * max(x,y);
-
- return h;
-}
-
-/**
- This heuristic only considers the stright line distance.
- Will usualy mean a lower H then G meaning A* Will speand more
- and run slower.
-**/
-float pathlib_h_euclidean(vector a,vector b)
-{
- return vlen(a - b);
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-**/
-float pathlib_h_diagonal2(vector a,vector b)
-{
- float h_diag,h_str,h,x,y;
-
- /*
- h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
- */
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
-
- h_diag = min(x,y);
- h_str = x + y;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
-
-/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
-
-
-**/
-float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
-{
- float h_diag,h_str,h,x,y,z;
-
- //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
- x = fabs(point_x - end_x);
- y = fabs(point_y - end_y);
- z = fabs(point_z - end_z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- float m;
- vector d1,d2;
-
- d1 = normalize(preprev - point);
- d2 = normalize(prev - point);
- m = vlen(d1-d2);
- //bprint("pathlib_h_diagonal2sdp-M = ",ftos(m),"\n");
-
- return h * m;
-}
-
-
-float pathlib_h_diagonal3(vector a,vector b)
-{
- float h_diag,h_str,h,x,y,z;
-
- //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
- //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
- //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
- x = fabs(a_x - b_x);
- y = fabs(a_y - b_y);
- z = fabs(a_z - b_z);
-
- h_diag = min3(x,y,z);
- h_str = x + y + z;
-
- h = pathlib_movecost_diag * h_diag;
- h += pathlib_movecost * (h_str - 2 * h_diag);
-
- return h;
-}
-
-//#define PATHLIB_USE_NODESCRAP
-#define PATHLIB_NODEEXPIRE 0.05
-float pathlib_scraplist_cnt;
-entity newnode()
-{
- entity n;
-#ifdef PATHLIB_USE_NODESCRAP
- if(pathlib_scraplist_cnt)
- {
- n = findentity(world,owner,scraplist);
- if(n)
- {
- --pathlib_scraplist_cnt;
- ++pathlib_recycle_cnt;
- return n;
- }
- else
- pathlib_scraplist_cnt = 0;
- }
-#endif
- ++pathlib_made_cnt;
- n = spawn();
-#ifdef PATHLIB_NODEEXPIRE
- n.think = SUB_Remove;
- n.nextthink = time + PATHLIB_NODEEXPIRE;
- return n;
-}
-
-void dumpnode(entity n)
-{
-#ifdef PATHLIB_USE_NODESCRAP
- ++pathlib_scraplist_cnt;
-
- n.path_next = world;
- n.path_prev = world;
- n.is_path_node = FALSE;
- n.owner = scraplist;
-#else
- //n.is_path_node = FALSE;
- n.think = SUB_Remove;
- n.nextthink = time;
-#endif
-}
-
-entity pathlib_mknode(vector where,entity parent)
-{
- entity node;
-
- node = newnode();
- node.is_path_node = TRUE;
- node.owner = openlist;
- node.path_prev = parent;
-
- setorigin(node, where);
-
- ++pathlib_open_cnt;
-
- node.medium = pointcontents(where);
-
- return node;
-}
-
-var float pathlib_expandnode(entity node, vector start, vector goal);
-float pathlib_expandnode_star(entity node, vector start, vector goal);
-float pathlib_expandnode_box(entity node, vector start, vector goal);
-
-var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
-float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
-{
- entity node;
- float h,g,f,doedge;
- vector where;
-
- ++pathlib_searched_cnt;
-
- if(inwater(parent.origin))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_swimnode;
- }
- else
- {
- if(inwater(to))
- {
- pathlib_expandnode = pathlib_expandnode_box;
- pathlib_movenode = pathlib_swimnode;
- }
- else
- {
-
- pathlib_expandnode = pathlib_expandnode_star;
- pathlib_movenode = pathlib_walknode;
- doedge = 1;
- }
- }
-
- where = pathlib_movenode(parent.origin,to,0);
- if not(pathlib_movenode_goodnode)
- return 0;
-
- if(doedge)
- if(edge_check(where,pathlib_edge_check_size))
- return 0;
-
- if(parent.path_prev)
- pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
-
- h = pathlib_heuristic(where,goal);
- g = pathlib_cost(parent,where,cost);
- f = g + h;
-
- node = findradius(where,pathlib_gridsize * 0.75);
- while(node)
- {
- if(node.is_path_node == TRUE)
- {
- ++pathlib_merge_cnt;
- if(node.owner == openlist)
- {
- if(node.pathlib_node_g > g)
- {
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
- node.path_prev = parent;
- }
-
- if not (best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
- }
-
- return 1;
- }
- node = node.chain;
- }
-
- node = pathlib_mknode(where,parent);
- node.pathlib_node_h = h;
- node.pathlib_node_g = g;
- node.pathlib_node_f = f;
-
- if not (best_open_node)
- best_open_node = node;
- else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
- best_open_node = node;
-
- return 1;
-}
-
-entity pathlib_getbestopen()
-{
- entity node;
- entity bestnode;
-
- if(best_open_node)
- {
- ++pathlib_bestcash_hits;
- pathlib_bestcash_saved += pathlib_open_cnt;
-
- return best_open_node;
- }
-
- node = findchainentity(owner,openlist);
- if(!node)
- return world;
-
- bestnode = node;
- while(node)
- {
- ++pathlib_bestopen_seached;
- if(node.pathlib_node_f < bestnode.pathlib_node_f)
- bestnode = node;
-
- node = node.chain;
- }
-
- return bestnode;
-}
-
-void pathlib_close_node(entity node,vector goal)
-{
-
- if(node.owner == closedlist)
- {
- dprint("Pathlib: Tried to close a closed node!\n");
- return;
- }
-
- if(node == best_open_node)
- best_open_node = world;
-
- ++pathlib_closed_cnt;
- --pathlib_open_cnt;
-
- node.owner = closedlist;
-
- if(vlen(node.origin - goal) <= pathlib_gridsize)
- {
- vector goalmove;
-
- goalmove = pathlib_walknode(node.origin,goal,1);
- if(pathlib_movenode_goodnode)
- {
- goal_node = node;
- pathlib_foundgoal = TRUE;
- }
- }
-}
-
-float pathlib_expandnode_star(entity node, vector start, vector goal)
-{
- vector point;
- vector where;
- float nodecnt;
-
- where = node.origin;
-
- v_forward = '1 0 0';
- v_right = '0 1 0';
-
- // Forward
- point = where + v_forward * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Back
- point = where - v_forward * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Right
- point = where + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Left
- point = where - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
- // Forward-right
- point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Forward-left
- point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-right
- point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- // Back-left
- point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
- nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
- return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_box(entity node, vector start, vector goal)
-{
- vector v;
-
- for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
- for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
- for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
- {
- if(vlen(v - node.origin))
- pathlib_makenode(node,start,v,goal,pathlib_movecost);
- }
-
- return pathlib_open_cnt;
-}
-
-void pathlib_cleanup()
-{
- entity node;
-
- node = findfloat(world,is_path_node, TRUE);
- while(node)
- {
- dumpnode(node);
- node = findfloat(node,is_path_node, TRUE);
- }
-
- if(openlist)
- remove(openlist);
-
- if(closedlist)
- remove(closedlist);
-
- best_open_node = world;
- openlist = world;
- closedlist = world;
-}
-
-var float buildpath_nodefilter(vector n,vector c,vector p);
-float buildpath_nodefilter_directional(vector n,vector c,vector p)
-{
- vector d1,d2;
-
- d2 = normalize(p - c);
- d1 = normalize(c - n);
-
- if(vlen(d1-d2) < 0.25)
- return 1;
-
- return 0;
-}
-
-float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
-{
- pathlib_walknode(p,n,1);
- if(pathlib_movenode_goodnode)
- return 1;
-
- return 0;
-}
-
-entity path_build(entity next, vector where, entity prev, entity start)
-{
- entity path;
-
- if(prev && next)
- if(buildpath_nodefilter)
- if(buildpath_nodefilter(next.origin,where,prev.origin))
- return next;
-
-
- path = spawn();
- path.owner = start;
- path.path_next = next;
-
- setorigin(path,where);
-
- if(!next)
- path.classname = "path_end";
- else
- {
- if(!prev)
- path.classname = "path_start";
- else
- path.classname = "path_node";
- }
-
- return path;
-}
-
-entity pathlib_astar(vector from,vector to)
-{
- entity path, start, end, open, n, ln;
- float ptime, ftime, ctime;
-
- ptime = gettime(GETTIME_REALTIME);
-
- pathlib_cleanup();
-
- // Select water<->land capable node make/link
- pathlib_makenode = pathlib_makenode_adaptive;
- // Select XYZ cost estimate
- pathlib_heuristic = pathlib_h_diagonal3;
- // Select distance + waterfactor cost
- pathlib_cost = pathlib_g_euclidean_water;
- // Select star expander
- pathlib_expandnode = pathlib_expandnode_star;
- // Select walk simulation movement test
- pathlib_movenode = pathlib_walknode;
- // Filter final nodes by direction
- buildpath_nodefilter = buildpath_nodefilter_directional;
-
- // If the start is in water we need diffrent settings
- if(inwater(from))
- {
- // Select volumetric node expaner
- pathlib_expandnode = pathlib_expandnode_box;
-
- // Water movement test
- pathlib_movenode = pathlib_swimnode;
- }
-
- if not(openlist)
- openlist = spawn();
-
- if not(closedlist)
- closedlist = spawn();
-
- if not(scraplist)
- scraplist = spawn();
-
- pathlib_closed_cnt = 0;
- pathlib_open_cnt = 0;
- pathlib_made_cnt = 0;
- pathlib_merge_cnt = 0;
- pathlib_searched_cnt = 0;
- pathlib_bestopen_seached = 0;
- pathlib_bestcash_hits = 0;
- pathlib_bestcash_saved = 0;
- pathlib_recycle_cnt = 0;
-
- pathlib_gridsize = 128;
- pathlib_movecost = pathlib_gridsize;
- pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
- pathlib_movecost_waterfactor = 1.1;
- pathlib_foundgoal = 0;
-
- walknode_boxmax = self.maxs * 1.5;
- walknode_boxmin = self.mins * 1.5;
-
- pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.5);
-
- walknode_boxup = '0 0 2' * self.maxs_z;
- walknode_stepsize = 32;
- walknode_stepup = '0 0 1' * walknode_stepsize;
- walknode_maxdrop = '0 0 3' * walknode_stepsize;
-
- from_x = fsnap(from_x,pathlib_gridsize);
- from_y = fsnap(from_y,pathlib_gridsize);
-
- to_x = fsnap(to_x,pathlib_gridsize);
- to_y = fsnap(to_y,pathlib_gridsize);
-
- dprint("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
- path = pathlib_mknode(from,world);
- pathlib_close_node(path,to);
- if(pathlib_foundgoal)
- {
- dprint("AStar: Goal found on first node!\n");
-
- open = spawn();
- open.owner = open;
- open.classname = "path_end";
- setorigin(open,path.origin);
-
- pathlib_cleanup();
-
- return open;
- }
-
- if(pathlib_expandnode(path,from,to) <= 0)
- {
- dprint("AStar path fail.\n");
- pathlib_cleanup();
-
- return world;
- }
-
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode_star(n,from,to);
-
- while(pathlib_open_cnt)
- {
- best_open_node = pathlib_getbestopen();
- n = best_open_node;
- pathlib_close_node(best_open_node,to);
-
- if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
- else
- pathlib_expandnode(n,from,to);
-
- if(pathlib_foundgoal)
- {
- dprint("Target found. Rebuilding and filtering path...\n");
- ftime = gettime(GETTIME_REALTIME);
- ptime = ftime - ptime;
-
- start = path_build(world,path.origin,world,world);
- end = path_build(world,goal_node.origin,world,start);
- ln = end;
-
- open = goal_node;
- for(open = goal_node; open.path_prev != path; open = open.path_prev)
- {
- n = path_build(ln,open.origin,open.path_prev,start);
- ln.path_prev = n;
- ln = n;
- }
- start.path_next = n;
- n.path_prev = start;
- ftime = gettime(GETTIME_REALTIME) - ftime;
-
- ctime = gettime(GETTIME_REALTIME);
- pathlib_cleanup();
- ctime = gettime(GETTIME_REALTIME) - ctime;
-
-
-#ifdef DEBUGPATHING
- pathlib_showpath2(start);
-
- dprint("Time used - pathfinding: ", ftos(ptime),"\n");
- dprint("Time used - rebuild & filter: ", ftos(ftime),"\n");
- dprint("Time used - cleanup: ", ftos(ctime),"\n");
- dprint("Time used - total: ", ftos(ptime + ftime + ctime),"\n");
- dprint("Time used - # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_ticrate)),"\n\n");
- dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
- dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
- dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
- dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
- dprint("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n");
-
- if(pathlib_recycle_cnt)
- dprint("Nodes - make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
- if(pathlib_recycle_cnt)
- dprint("Nodes - reused: ", ftos(pathlib_recycle_cnt),"\n");
-
- dprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
- dprint("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n");
- dprint("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n");
- dprint("AStar done. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
-#endif
- return start;
- }
- }
-
- dprint("A* Faild to find a path! Try a smaller gridsize.\n");
-
- pathlib_cleanup();
-
- return world;
-}
-
-
-
+//#define PATHLIB_RDFIELDS
+#ifdef PATHLIB_RDFIELDS
+ #define path_next swampslug
+ #define path_prev lasertarget
+#else
+ .entity path_next;
+ .entity path_prev;
+#endif
+
+#define medium spawnshieldtime
+
+//#define DEBUGPATHING
+
+entity openlist;
+entity closedlist;
+entity scraplist;
+
+.float pathlib_node_g;
+.float pathlib_node_h;
+.float pathlib_node_f;
+
+float pathlib_open_cnt;
+float pathlib_closed_cnt;
+float pathlib_made_cnt;
+float pathlib_merge_cnt;
+float pathlib_recycle_cnt;
+float pathlib_searched_cnt;
+
+#ifdef DEBUGPATHING
+
+#endif
+
+float pathlib_bestopen_seached;
+float pathlib_bestcash_hits;
+float pathlib_bestcash_saved;
+
+float pathlib_gridsize;
+
+float pathlib_movecost;
+float pathlib_movecost_diag;
+float pathlib_movecost_waterfactor;
+
+float pathlib_edge_check_size;
+
+float pathlib_foundgoal;
+entity goal_node;
+
+entity best_open_node;
+.float is_path_node;
+
+
+#ifdef DEBUGPATHING
+float edge_show(vector point,float fsize);
+void mark_error(vector where,float lifetime);
+void mark_info(vector where,float lifetime);
+entity mark_misc(vector where,float lifetime);
+
+void pathlib_showpath(entity start)
+{
+ entity e;
+ e = start;
+ while(e.path_next)
+ {
+ te_lightning1(e,e.origin,e.path_next.origin);
+ e = e.path_next;
+ }
+}
+
+void path_dbg_think()
+{
+ pathlib_showpath(self);
+ self.nextthink = time + 1;
+}
+
+void __showpath2_think()
+{
+ mark_info(self.origin,1);
+ if(self.path_next)
+ {
+ self.path_next.think = __showpath2_think;
+ self.path_next.nextthink = time + 0.15;
+ }
+ else
+ {
+ self.owner.think = __showpath2_think;
+ self.owner.nextthink = time + 0.15;
+ }
+}
+
+void pathlib_showpath2(entity path)
+{
+ path.think = __showpath2_think;
+ path.nextthink = time;
+}
+
+#endif
+
+void pathlib_deletepath(entity start)
+{
+ entity e;
+
+ e = findchainentity(owner, start);
+ while(e)
+ {
+ e.think = SUB_Remove;
+ e.nextthink = time;
+ e = e.chain;
+ }
+}
+
+float fsnap(float val,float fsize)
+{
+ return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+ vector vret;
+
+ vret_x = rint(point_x / fsize) * fsize;
+ vret_y = rint(point_y / fsize) * fsize;
+ vret_z = ceil(point_z / fsize) * fsize;
+
+ return vret;
+}
+
+float walknode_stepsize;
+vector walknode_stepup;
+vector walknode_maxdrop;
+vector walknode_boxup;
+vector walknode_boxmax;
+vector walknode_boxmin;
+float pathlib_movenode_goodnode;
+
+float floor_ok(vector point)
+{
+ float pc;
+
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ return 0;
+
+ pc = pointcontents(point);
+
+ switch(pc)
+ {
+ case CONTENT_SOLID:
+ case CONTENT_SLIME:
+ case CONTENT_LAVA:
+ case CONTENT_SKY:
+ return 0;
+ case CONTENT_EMPTY:
+ if not (pointcontents(point - '0 0 1') == CONTENT_SOLID)
+ return 0;
+ break;
+ case CONTENT_WATER:
+ return 1;
+ }
+ if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
+ return 1;
+
+ return 0;
+}
+
+#define inwater(point) (pointcontents(point) == CONTENT_WATER)
+/*
+float inwater(vector point)
+{
+ if(pointcontents(point) == CONTENT_WATER)
+ return 1;
+ return 0;
+}
+*/
+
+#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if not(floor_ok(trace_endpos)) return 1
+float edge_check(vector point,float fsize)
+{
+ vector z_up,z_down;
+
+ z_up = '0 0 1' * fsize;
+ z_down = '0 0 1' * fsize;
+
+ _pcheck(point + ('1 1 0' * fsize));
+ _pcheck(point + ('1 -1 0' * fsize));
+ _pcheck(point + ('1 0 0' * fsize));
+
+ _pcheck(point + ('0 1 0' * fsize));
+ _pcheck(point + ('0 -1 0' * fsize));
+
+ _pcheck(point + ('-1 0 0' * fsize));
+ _pcheck(point + ('-1 1 0' * fsize));
+ _pcheck(point + ('-1 -1 0' * fsize));
+
+ return 0;
+}
+
+#ifdef DEBUGPATHING
+#define _pshow(p) mark_error(p,10)
+float edge_show(vector point,float fsize)
+{
+
+ _pshow(point + ('1 1 0' * fsize));
+ _pshow(point + ('1 -1 0' * fsize));
+ _pshow(point + ('1 0 0' * fsize));
+
+ _pshow(point + ('0 1 0' * fsize));
+ _pshow(point + ('0 -1 0' * fsize));
+
+ _pshow(point + ('-1 0 0' * fsize));
+ _pshow(point + ('-1 1 0' * fsize));
+ _pshow(point + ('-1 -1 0' * fsize));
+
+ return 0;
+}
+#endif
+
+var vector pathlib_movenode(vector start,vector end,float doedge);
+vector pathlib_wateroutnode(vector start,vector end)
+{
+ vector surface;
+
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
+ end = trace_endpos;
+
+ if not(pointcontents(end - '0 0 1') == CONTENT_SOLID)
+ return end;
+
+ for(surface = start ; surface_z < (end_z + 32); ++surface_z)
+ {
+ if(pointcontents(surface) == CONTENT_EMPTY)
+ break;
+ }
+
+ if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
+ return end;
+
+ tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ if(fabs(surface_z - end_z) > 32)
+ pathlib_movenode_goodnode = 0;
+
+ return end;
+}
+
+vector pathlib_swimnode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ if(pointcontents(start) != CONTENT_WATER)
+ return end;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ if(pointcontents(end) == CONTENT_EMPTY)
+ return pathlib_wateroutnode( start, end);
+
+ tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_flynode(vector start,vector end)
+{
+ pathlib_movenode_goodnode = 0;
+
+ end_x = fsnap(end_x, pathlib_gridsize);
+ end_y = fsnap(end_y, pathlib_gridsize);
+
+ tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
+ if(trace_fraction == 1)
+ pathlib_movenode_goodnode = 1;
+
+ return end;
+}
+
+vector pathlib_walknode(vector start,vector end,float doedge)
+{
+ vector direction,point,last_point,s,e;
+ float steps, distance, i,laststep;
+
+ pathlib_movenode_goodnode = 0;
+
+ s = start;
+ e = end;
+ e_z = 0;
+ s_z = 0;
+ direction = normalize(s - e);
+
+ distance = vlen(start - end);
+ laststep = distance / walknode_stepsize;
+ steps = floor(laststep);
+ laststep = laststep - steps;
+
+ point = start;
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+
+ traceline(s, e,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ if (floor_ok(trace_endpos) == 0)
+ return trace_endpos;
+
+ last_point = trace_endpos;
+
+ for(i = 0; i < steps; ++i)
+ {
+ point = last_point + direction * walknode_stepsize;
+
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+ traceline(s, e,MOVE_WORLDONLY,self);
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ point = trace_endpos;
+ if not(floor_ok(trace_endpos))
+ return trace_endpos;
+
+ tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
+ if(trace_fraction != 1.0)
+ return trace_endpos;
+
+ if(doedge)
+ if(edge_check(point,pathlib_edge_check_size))
+ return trace_endpos;
+
+ last_point = point;
+ }
+
+ point = last_point + direction * walknode_stepsize * laststep;
+
+ point_x = fsnap(point_x, pathlib_gridsize);
+ point_y = fsnap(point_y, pathlib_gridsize);
+
+ s = point + walknode_stepup;
+ e = point - walknode_maxdrop;
+ traceline(s, e,MOVE_WORLDONLY,self);
+
+ if(trace_fraction == 1.0)
+ return trace_endpos;
+
+ point = trace_endpos;
+
+ if not(floor_ok(trace_endpos))
+ return trace_endpos;
+
+ tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
+ if(trace_fraction != 1.0)
+ return trace_endpos;
+
+ pathlib_movenode_goodnode = 1;
+ return point;
+}
+
+var float pathlib_cost(entity parent,vector to, float static_cost);
+float pathlib_g_static(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_static_water(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + static_cost;
+}
+
+float pathlib_g_euclidean(entity parent,vector to, float static_cost)
+{
+ return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
+{
+ if(inwater(to))
+ return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
+ else
+ return parent.pathlib_node_g + vlen(parent.origin - to);
+}
+
+var float(vector from,vector to) pathlib_heuristic;
+
+/**
+ Manhattan Menas we expect to move up,down left or right
+ No diagonal moves espected. (like moving bewteen city blocks)
+**/
+float pathlib_h_manhattan(vector a,vector b)
+{
+ //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
+
+ float h;
+ h = fabs(a_x - b_x);
+ h += fabs(a_y - b_y);
+ h *= pathlib_gridsize;
+
+ return h;
+}
+
+/**
+ This heuristic consider both stright and disagonal moves
+ to have teh same cost.
+**/
+float pathlib_h_diagonal(vector a,vector b)
+{
+ //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
+ float h,x,y;
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ h = pathlib_movecost * max(x,y);
+
+ return h;
+}
+
+/**
+ This heuristic only considers the stright line distance.
+ Will usualy mean a lower H then G meaning A* Will speand more
+ and run slower.
+**/
+float pathlib_h_euclidean(vector a,vector b)
+{
+ return vlen(a - b);
+}
+
+/**
+ This heuristic consider both stright and disagonal moves,
+ But has a separate cost for diagonal moves.
+**/
+float pathlib_h_diagonal2(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y;
+
+ /*
+ h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+ */
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+
+ h_diag = min(x,y);
+ h_str = x + y;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h;
+}
+
+/**
+ This heuristic consider both stright and disagonal moves,
+ But has a separate cost for diagonal moves.
+
+
+**/
+float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+ x = fabs(point_x - end_x);
+ y = fabs(point_y - end_y);
+ z = fabs(point_z - end_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ float m;
+ vector d1,d2;
+
+ d1 = normalize(preprev - point);
+ d2 = normalize(prev - point);
+ m = vlen(d1-d2);
+ //bprint("pathlib_h_diagonal2sdp-M = ",ftos(m),"\n");
+
+ return h * m;
+}
+
+
+float pathlib_h_diagonal3(vector a,vector b)
+{
+ float h_diag,h_str,h,x,y,z;
+
+ //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
+ //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
+ //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
+
+ x = fabs(a_x - b_x);
+ y = fabs(a_y - b_y);
+ z = fabs(a_z - b_z);
+
+ h_diag = min3(x,y,z);
+ h_str = x + y + z;
+
+ h = pathlib_movecost_diag * h_diag;
+ h += pathlib_movecost * (h_str - 2 * h_diag);
+
+ return h;
+}
+
+//#define PATHLIB_USE_NODESCRAP
+#define PATHLIB_NODEEXPIRE 0.05
+float pathlib_scraplist_cnt;
+entity newnode()
+{
+ entity n;
+#ifdef PATHLIB_USE_NODESCRAP
+ if(pathlib_scraplist_cnt)
+ {
+ n = findentity(world,owner,scraplist);
+ if(n)
+ {
+ --pathlib_scraplist_cnt;
+ ++pathlib_recycle_cnt;
+ return n;
+ }
+ else
+ pathlib_scraplist_cnt = 0;
+ }
+#endif
+ ++pathlib_made_cnt;
+ n = spawn();
+#ifdef PATHLIB_NODEEXPIRE
+ n.think = SUB_Remove;
+ n.nextthink = time + PATHLIB_NODEEXPIRE;
+ return n;
+}
+
+void dumpnode(entity n)
+{
+#ifdef PATHLIB_USE_NODESCRAP
+ ++pathlib_scraplist_cnt;
+
+ n.path_next = world;
+ n.path_prev = world;
+ n.is_path_node = FALSE;
+ n.owner = scraplist;
+#else
+ //n.is_path_node = FALSE;
+ n.think = SUB_Remove;
+ n.nextthink = time;
+#endif
+}
+
+entity pathlib_mknode(vector where,entity parent)
+{
+ entity node;
+
+ node = newnode();
+ node.is_path_node = TRUE;
+ node.owner = openlist;
+ node.path_prev = parent;
+
+ setorigin(node, where);
+
+ ++pathlib_open_cnt;
+
+ node.medium = pointcontents(where);
+
+ return node;
+}
+
+var float pathlib_expandnode(entity node, vector start, vector goal);
+float pathlib_expandnode_star(entity node, vector start, vector goal);
+float pathlib_expandnode_box(entity node, vector start, vector goal);
+
+var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
+float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
+{
+ entity node;
+ float h,g,f,doedge;
+ vector where;
+
+ ++pathlib_searched_cnt;
+
+ if(inwater(parent.origin))
+ {
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ else
+ {
+ if(inwater(to))
+ {
+ pathlib_expandnode = pathlib_expandnode_box;
+ pathlib_movenode = pathlib_swimnode;
+ }
+ else
+ {
+
+ pathlib_expandnode = pathlib_expandnode_star;
+ pathlib_movenode = pathlib_walknode;
+ doedge = 1;
+ }
+ }
+
+ where = pathlib_movenode(parent.origin,to,0);
+ if not(pathlib_movenode_goodnode)
+ return 0;
+
+ if(doedge)
+ if(edge_check(where,pathlib_edge_check_size))
+ return 0;
+
+ if(parent.path_prev)
+ pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
+
+ h = pathlib_heuristic(where,goal);
+ g = pathlib_cost(parent,where,cost);
+ f = g + h;
+
+ node = findradius(where,pathlib_gridsize * 0.75);
+ while(node)
+ {
+ if(node.is_path_node == TRUE)
+ {
+ ++pathlib_merge_cnt;
+ if(node.owner == openlist)
+ {
+ if(node.pathlib_node_g > g)
+ {
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+ node.path_prev = parent;
+ }
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+ }
+
+ return 1;
+ }
+ node = node.chain;
+ }
+
+ node = pathlib_mknode(where,parent);
+ node.pathlib_node_h = h;
+ node.pathlib_node_g = g;
+ node.pathlib_node_f = f;
+
+ if not (best_open_node)
+ best_open_node = node;
+ else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
+ best_open_node = node;
+
+ return 1;
+}
+
+entity pathlib_getbestopen()
+{
+ entity node;
+ entity bestnode;
+
+ if(best_open_node)
+ {
+ ++pathlib_bestcash_hits;
+ pathlib_bestcash_saved += pathlib_open_cnt;
+
+ return best_open_node;
+ }
+
+ node = findchainentity(owner,openlist);
+ if(!node)
+ return world;
+
+ bestnode = node;
+ while(node)
+ {
+ ++pathlib_bestopen_seached;
+ if(node.pathlib_node_f < bestnode.pathlib_node_f)
+ bestnode = node;
+
+ node = node.chain;
+ }
+
+ return bestnode;
+}
+
+void pathlib_close_node(entity node,vector goal)
+{
+
+ if(node.owner == closedlist)
+ {
+ dprint("Pathlib: Tried to close a closed node!\n");
+ return;
+ }
+
+ if(node == best_open_node)
+ best_open_node = world;
+
+ ++pathlib_closed_cnt;
+ --pathlib_open_cnt;
+
+ node.owner = closedlist;
+
+ if(vlen(node.origin - goal) <= pathlib_gridsize)
+ {
+ vector goalmove;
+
+ goalmove = pathlib_walknode(node.origin,goal,1);
+ if(pathlib_movenode_goodnode)
+ {
+ goal_node = node;
+ pathlib_foundgoal = TRUE;
+ }
+ }
+}
+
+float pathlib_expandnode_star(entity node, vector start, vector goal)
+{
+ vector point;
+ vector where;
+ float nodecnt;
+
+ where = node.origin;
+
+ v_forward = '1 0 0';
+ v_right = '0 1 0';
+
+ // Forward
+ point = where + v_forward * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Back
+ point = where - v_forward * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Right
+ point = where + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Left
+ point = where - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
+
+ // Forward-right
+ point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Forward-left
+ point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-right
+ point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ // Back-left
+ point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
+ nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+
+ return pathlib_open_cnt;
+}
+
+float pathlib_expandnode_box(entity node, vector start, vector goal)
+{
+ vector v;
+
+ for(v_z = node.origin_z - pathlib_gridsize; v_z <= node.origin_z + pathlib_gridsize; v_z += pathlib_gridsize)
+ for(v_y = node.origin_y - pathlib_gridsize; v_y <= node.origin_y + pathlib_gridsize; v_y += pathlib_gridsize)
+ for(v_x = node.origin_x - pathlib_gridsize; v_x <= node.origin_x + pathlib_gridsize; v_x += pathlib_gridsize)
+ {
+ if(vlen(v - node.origin))
+ pathlib_makenode(node,start,v,goal,pathlib_movecost);
+ }
+
+ return pathlib_open_cnt;
+}
+
+void pathlib_cleanup()
+{
+ entity node;
+
+ node = findfloat(world,is_path_node, TRUE);
+ while(node)
+ {
+ dumpnode(node);
+ node = findfloat(node,is_path_node, TRUE);
+ }
+
+ if(openlist)
+ remove(openlist);
+
+ if(closedlist)
+ remove(closedlist);
+
+ best_open_node = world;
+ openlist = world;
+ closedlist = world;
+}
+
+var float buildpath_nodefilter(vector n,vector c,vector p);
+float buildpath_nodefilter_directional(vector n,vector c,vector p)
+{
+ vector d1,d2;
+
+ d2 = normalize(p - c);
+ d1 = normalize(c - n);
+
+ if(vlen(d1-d2) < 0.25)
+ return 1;
+
+ return 0;
+}
+
+float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
+{
+ pathlib_walknode(p,n,1);
+ if(pathlib_movenode_goodnode)
+ return 1;
+
+ return 0;
+}
+
+entity path_build(entity next, vector where, entity prev, entity start)
+{
+ entity path;
+
+ if(prev && next)
+ if(buildpath_nodefilter)
+ if(buildpath_nodefilter(next.origin,where,prev.origin))
+ return next;
+
+
+ path = spawn();
+ path.owner = start;
+ path.path_next = next;
+
+ setorigin(path,where);
+
+ if(!next)
+ path.classname = "path_end";
+ else
+ {
+ if(!prev)
+ path.classname = "path_start";
+ else
+ path.classname = "path_node";
+ }
+
+ return path;
+}
+
+entity pathlib_astar(vector from,vector to)
+{
+ entity path, start, end, open, n, ln;
+ float ptime, ftime, ctime;
+
+ ptime = gettime(GETTIME_REALTIME);
+
+ pathlib_cleanup();
+
+ // Select water<->land capable node make/link
+ pathlib_makenode = pathlib_makenode_adaptive;
+ // Select XYZ cost estimate
+ pathlib_heuristic = pathlib_h_diagonal3;
+ // Select distance + waterfactor cost
+ pathlib_cost = pathlib_g_euclidean_water;
+ // Select star expander
+ pathlib_expandnode = pathlib_expandnode_star;
+ // Select walk simulation movement test
+ pathlib_movenode = pathlib_walknode;
+ // Filter final nodes by direction
+ buildpath_nodefilter = buildpath_nodefilter_directional;
+
+ // If the start is in water we need diffrent settings
+ if(inwater(from))
+ {
+ // Select volumetric node expaner
+ pathlib_expandnode = pathlib_expandnode_box;
+
+ // Water movement test
+ pathlib_movenode = pathlib_swimnode;
+ }
+
+ if not(openlist)
+ openlist = spawn();
+
+ if not(closedlist)
+ closedlist = spawn();
+
+ if not(scraplist)
+ scraplist = spawn();
+
+ pathlib_closed_cnt = 0;
+ pathlib_open_cnt = 0;
+ pathlib_made_cnt = 0;
+ pathlib_merge_cnt = 0;
+ pathlib_searched_cnt = 0;
+ pathlib_bestopen_seached = 0;
+ pathlib_bestcash_hits = 0;
+ pathlib_bestcash_saved = 0;
+ pathlib_recycle_cnt = 0;
+
+ pathlib_gridsize = 128;
+ pathlib_movecost = pathlib_gridsize;
+ pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
+ pathlib_movecost_waterfactor = 1.1;
+ pathlib_foundgoal = 0;
+
+ walknode_boxmax = self.maxs * 1.5;
+ walknode_boxmin = self.mins * 1.5;
+
+ pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.5);
+
+ walknode_boxup = '0 0 2' * self.maxs_z;
+ walknode_stepsize = 32;
+ walknode_stepup = '0 0 1' * walknode_stepsize;
+ walknode_maxdrop = '0 0 3' * walknode_stepsize;
+
+ from_x = fsnap(from_x,pathlib_gridsize);
+ from_y = fsnap(from_y,pathlib_gridsize);
+
+ to_x = fsnap(to_x,pathlib_gridsize);
+ to_y = fsnap(to_y,pathlib_gridsize);
+
+ dprint("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
+ path = pathlib_mknode(from,world);
+ pathlib_close_node(path,to);
+ if(pathlib_foundgoal)
+ {
+ dprint("AStar: Goal found on first node!\n");
+
+ open = spawn();
+ open.owner = open;
+ open.classname = "path_end";
+ setorigin(open,path.origin);
+
+ pathlib_cleanup();
+
+ return open;
+ }
+
+ if(pathlib_expandnode(path,from,to) <= 0)
+ {
+ dprint("AStar path fail.\n");
+ pathlib_cleanup();
+
+ return world;
+ }
+
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode_star(n,from,to);
+
+ while(pathlib_open_cnt)
+ {
+ best_open_node = pathlib_getbestopen();
+ n = best_open_node;
+ pathlib_close_node(best_open_node,to);
+
+ if(inwater(n.origin))
+ pathlib_expandnode_box(n,from,to);
+ else
+ pathlib_expandnode(n,from,to);
+
+ if(pathlib_foundgoal)
+ {
+ dprint("Target found. Rebuilding and filtering path...\n");
+ ftime = gettime(GETTIME_REALTIME);
+ ptime = ftime - ptime;
+
+ start = path_build(world,path.origin,world,world);
+ end = path_build(world,goal_node.origin,world,start);
+ ln = end;
+
+ open = goal_node;
+ for(open = goal_node; open.path_prev != path; open = open.path_prev)
+ {
+ n = path_build(ln,open.origin,open.path_prev,start);
+ ln.path_prev = n;
+ ln = n;
+ }
+ start.path_next = n;
+ n.path_prev = start;
+ ftime = gettime(GETTIME_REALTIME) - ftime;
+
+ ctime = gettime(GETTIME_REALTIME);
+ pathlib_cleanup();
+ ctime = gettime(GETTIME_REALTIME) - ctime;
+
+
+#ifdef DEBUGPATHING
+ pathlib_showpath2(start);
+
+ dprint("Time used - pathfinding: ", ftos(ptime),"\n");
+ dprint("Time used - rebuild & filter: ", ftos(ftime),"\n");
+ dprint("Time used - cleanup: ", ftos(ctime),"\n");
+ dprint("Time used - total: ", ftos(ptime + ftime + ctime),"\n");
+ dprint("Time used - # frames: ", ftos(ceil((ptime + ftime + ctime) / sys_ticrate)),"\n\n");
+ dprint("Nodes - created: ", ftos(pathlib_made_cnt),"\n");
+ dprint("Nodes - open: ", ftos(pathlib_open_cnt),"\n");
+ dprint("Nodes - merged: ", ftos(pathlib_merge_cnt),"\n");
+ dprint("Nodes - closed: ", ftos(pathlib_closed_cnt),"\n");
+ dprint("Nodes - searched: ", ftos(pathlib_searched_cnt),"\n");
+
+ if(pathlib_recycle_cnt)
+ dprint("Nodes - make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
+ if(pathlib_recycle_cnt)
+ dprint("Nodes - reused: ", ftos(pathlib_recycle_cnt),"\n");
+
+ dprint("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\n");
+ dprint("Nodes bestcash - hits: ", ftos(pathlib_bestcash_hits),"\n");
+ dprint("Nodes bestcash - save: ", ftos(pathlib_bestcash_saved),"\n");
+ dprint("AStar done. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
+#endif
+ return start;
+ }
+ }
+
+ dprint("A* Faild to find a path! Try a smaller gridsize.\n");
+
+ pathlib_cleanup();
+
+ return world;
+}
+
+
+
Property changes on: trunk/data/qcsrc/server/pathlib.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/portals.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/portals.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/post-builtins.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/pre-builtins.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/race.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/race.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/scores.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/scores.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/scores_rules.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/steerlib.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/target_spawn.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/include/turrets.qh
===================================================================
--- trunk/data/qcsrc/server/tturrets/include/turrets.qh 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/include/turrets.qh 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,29 +1,29 @@
-#ifdef TTURRETS_ENABLED
-
-// Include section.
-#include "../system/system_misc.qc" /// Assorted junk & jewls
-#include "../system/system_main.qc" /// And routines
-#include "../system/system_aimprocs.qc" /// Aiming realted stuff
-#include "../system/system_scoreprocs.qc" /// Target calssification
-#include "../system/system_damage.qc" /// Outch, they are hurting me! what should i do?
-
-// Non combat units
-#include "../units/unit_fusionreactor.qc" /// Supply unites that need it with power
-#include "../units/unit_targettrigger.qc" /// Hit me!
-#include "../units/unit_checkpoint.qc" /// Halfsmart pathing.
-
-// Combat units
-#include "../units/unit_plasma.qc" /// Basic energy cannon
-#include "../units/unit_mlrs.qc" /// Basic multibay RL
-#include "../units/unit_hellion.qc" /// Seeking missiles MLRS
-#include "../units/unit_flac.qc" /// anti missile turret
-#include "../units/unit_phaser.qc" /// ZzzapT
-#include "../units/unit_hk.qc" /// Hunter killers
-#include "../units/unit_machinegun.qc" /// whacka
-#include "../units/unit_tessla.qc" /// Chain lightning capabale turret
-#include "../units/unit_walker.qc" /// Moving minigun-rocket-meele err thing
-#include "../units/unit_ewheel.qc" /// A evil wheel. with guns on.
-//#include "../units/unit_repulsor.qc" /// Fires a wave that knocks foes back
-//#include "../units/unit_hive.qc" /// Swarm AI
-
-#endif // TTURRETS_ENABLED
+#ifdef TTURRETS_ENABLED
+
+// Include section.
+#include "../system/system_misc.qc" /// Assorted junk & jewls
+#include "../system/system_main.qc" /// And routines
+#include "../system/system_aimprocs.qc" /// Aiming realted stuff
+#include "../system/system_scoreprocs.qc" /// Target calssification
+#include "../system/system_damage.qc" /// Outch, they are hurting me! what should i do?
+
+// Non combat units
+#include "../units/unit_fusionreactor.qc" /// Supply unites that need it with power
+#include "../units/unit_targettrigger.qc" /// Hit me!
+#include "../units/unit_checkpoint.qc" /// Halfsmart pathing.
+
+// Combat units
+#include "../units/unit_plasma.qc" /// Basic energy cannon
+#include "../units/unit_mlrs.qc" /// Basic multibay RL
+#include "../units/unit_hellion.qc" /// Seeking missiles MLRS
+#include "../units/unit_flac.qc" /// anti missile turret
+#include "../units/unit_phaser.qc" /// ZzzapT
+#include "../units/unit_hk.qc" /// Hunter killers
+#include "../units/unit_machinegun.qc" /// whacka
+#include "../units/unit_tessla.qc" /// Chain lightning capabale turret
+#include "../units/unit_walker.qc" /// Moving minigun-rocket-meele err thing
+#include "../units/unit_ewheel.qc" /// A evil wheel. with guns on.
+//#include "../units/unit_repulsor.qc" /// Fires a wave that knocks foes back
+//#include "../units/unit_hive.qc" /// Swarm AI
+
+#endif // TTURRETS_ENABLED
Property changes on: trunk/data/qcsrc/server/tturrets/include/turrets.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/include/turrets_early.qh
===================================================================
--- trunk/data/qcsrc/server/tturrets/include/turrets_early.qh 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/include/turrets_early.qh 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,533 +1,533 @@
-// Comment out below to skip turrets
-#define TTURRETS_ENABLED
-
-#ifdef TTURRETS_ENABLED
-
-#message "with tZork turrets"
-
-vector real_origin(entity ent);
-
-/// Map time control over pain inflicted
-.float turret_scale_damage;
-/// Map time control targetting range
-.float turret_scale_range;
-/// Map time control refire
-.float turret_scale_refire;
-/// Map time control ammo held and recharged
-.float turret_scale_ammo;
-/// Map time control aim speed
-.float turret_scale_aim;
-/// Map time control health
-.float turret_scale_health;
-/// Map time control respawn time
-.float turret_scale_respawn;
-
-/// Used for cvar reloading
-.string cvar_basename;
-
-//.float spawnflags
-/// Spawn a pillar model under the turret to make it look ok on uneven ground surfaces
-#define TSF_TERRAINBASE 2
-/// Disable builtin ammo regeneration
-#define TSF_NO_AMMO_REGEN 4
-/// Dont break path to chase enemys. will still fire at them if possible.
-#define TSF_NO_PATHBREAK 8
-/// Dont respawn
-#define TSL_NO_RESPAWN 16
-
-/// target selection flags
-.float target_select_flags;
-/// target validatoin flags
-.float target_validate_flags;
-/// Dont select a target on its own.
-#define TFL_TARGETSELECT_NO 2
-/// Need line of sight
-#define TFL_TARGETSELECT_LOS 4
-/// Players are valid targets
-#define TFL_TARGETSELECT_PLAYERS 8
-/// Missiles are valid targets
-#define TFL_TARGETSELECT_MISSILES 16
-/// Responds to turret_trigger_target events
-#define TFL_TARGETSELECT_TRIGGERTARGET 32
-/// Angular limitations of turret head limits target selection
-#define TFL_TARGETSELECT_ANGLELIMITS 64
-/// Range limits apply in targetselection
-#define TFL_TARGETSELECT_RANGELIMTS 128
-/// DOnt select targets with a .team matching its own
-#define TFL_TARGETSELECT_TEAMCHECK 256
-/// Cant select targets on its own. needs to be triggerd or slaved.
-#define TFL_TARGETSELECT_NOBUILTIN 512
-/// TFL_TARGETSELECT_TEAMCHECK is inverted (selects only mebers of own .team)
-#define TFL_TARGETSELECT_OWNTEAM 1024
-/// Turrets aren't valid targets
-#define TFL_TARGETSELECT_NOTURRETS 2048
-/// Use feild of view
-#define TFL_TARGETSELECT_FOV 4096
-
-/// aim flags
-.float aim_flags;
-/// Dont aim.
-#define TFL_AIM_NO 1
-/// Go for ground, not direct hit
-#define TFL_AIM_GROUND 2
-/// Go for ground, not direct hit, but only if target is on ground.
-#define TFL_AIM_GROUND2 4
-/// Use balistic aim. FIXME: not implemented
-#define TFL_AIM_BALISTIC 8
-/// Try to predict target movement (does not account for gravity)
-#define TFL_AIM_LEAD 16
-/// Compensate for shot traveltime when lead
-#define TFL_AIM_SHOTTIMECOMPENSATE 32
-/// Aim slightly in front of target
-#define TFL_AIM_INFRONT 64
-/// Aim slightly behind target
-#define TFL_AIM_BEHIND 128
-/// blend real and predicted z positions. (fake bounce prediction)
-#define TFL_AIM_ZEASE 256
-/// Try to do real prediction of targets z pos at impact.
-#define TFL_AIM_ZPREDICT 512
-/// Simply aim at target's current location
-#define TFL_AIM_SIMPLE 1024
-
-/// track (turn and pitch head) flags
-.float track_flags;
-/// Dont move head
-#define TFL_TRACK_NO 2
-/// Pitch the head
-#define TFL_TRACK_PITCH 4
-/// Rotate the head
-#define TFL_TRACK_ROT 8
-
-/// How tracking is preformed
-.float track_type;
-/// Hard angle increments. Ugly for fast turning, best accuracy.
-#define TFL_TRACKTYPE_STEPMOTOR 1
-/// Smoth absolute movement. Looks ok, fair accuracy.
-#define TFL_TRACKTYPE_FLUIDPRECISE 2
-/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the feilds below are set
-#define TFL_TRACKTYPE_FLUIDINERTIA 3
-/// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier
-.float track_accel_pitch;
-/// TFL_TRACKTYPE_FLUIDINERTIA: rotation multiplier
-.float track_accel_rot;
-/// TFL_TRACKTYPE_FLUIDINERTIA: Blendrate with old rotation (inertia simulation) 1 = only old, 0 = only new
-.float track_blendrate;
-
-/// How prefire check is preformed
-.float firecheck_flags;
-/// Dont kill the world
-#define TFL_FIRECHECK_WORLD 2
-/// Dont kill the dead
-#define TFL_FIRECHECK_DEAD 4
-/// Range limits apply
-#define TFL_FIRECHECK_DISTANCES 8
-/// Line Of Sight needs to be clear
-#define TFL_FIRECHECK_LOS 16
-/// Consider distance inpactpoint<->aimspot
-#define TFL_FIRECHECK_AIMDIST 32
-/// Consider enemy origin<->impactpoint
-#define TFL_FIRECHECK_REALDIST 64
-/// Consider angular diff head<->aimspot
-#define TFL_FIRECHECK_ANGLEDIST 128
-/// (re)consider target.team<->self.team
-#define TFL_FIRECHECK_TEAMCECK 256
-/// Try to avoid friendly fire
-#define TFL_FIRECHECK_AFF 512
-/// Own .ammo needs to be >= then own .shot_dmg
-#define TFL_FIRECHECK_OWM_AMMO 1024
-/// Others ammo need to be < others .ammo_max
-#define TFL_FIRECHECK_OTHER_AMMO 2048
-/// Check own .attack_finished_single vs time
-#define TFL_FIRECHECK_REFIRE 4096
-/// Move the acctual target to aimspot before tracing impact (and back after)
-#define TFL_FIRECHECK_VERIFIED 8192
-/// Dont do any chekcs
-#define TFL_FIRECHECK_NO 16384
-
-/// How shooting is done
-.float shoot_flags;
-/// Dont shoot
-#define TFL_SHOOT_NO 64
-/// Fire in vollys (partial implementation through .shot_volly)
-#define TFL_SHOOT_VOLLY 2
-/// Always do a full volly, even if target is lost or dead. (not implemented)
-#define TFL_SHOOT_VOLLYALWAYS 4
-/// Loop though all valid tarters, and hit them.
-#define TFL_SHOOT_HITALLVALID 8
-/// Fiering makes unit loose target (after volly is done, if in volly mode)
-#define TFL_SHOOT_CLEARTARGET 16
-///Custom shooting;
-#define TFL_SHOOT_CUSTOM 32
-
-/// Information aboute the units capabilities
-.float turrcaps_flags;
-/// No kown capabilities
-#define TFL_TURRCAPS_NONE 0
-/// Capable of sniping
-#define TFL_TURRCAPS_SNIPER 2
-/// Capable of splasdamage
-#define TFL_TURRCAPS_RADIUSDMG 4
-/// Has one or more cannons with zero shot traveltime
-#define TFL_TURRCAPS_HITSCAN 8
-/// More then one (type of) gun
-#define TFL_TURRCAPS_MULTIGUN 16
-/// Carries at least one guided weapon
-#define TFL_TURRCAPS_GUIDED 32
-/// At least one gun fiers slow projectiles
-#define TFL_TURRCAPS_SLOWPROJ 64
-/// At least one gun fiers medium speed projectiles
-#define TFL_TURRCAPS_MEDPROJ 128
-/// At least one gun fiers fast projectiles
-#define TFL_TURRCAPS_FASTPROJ 256
-/// At least one gun capable of damaging players
-#define TFL_TURRCAPS_PLAYERKILL 512
-/// At least one gun that can shoot town missiles
-#define TFL_TURRCAPS_MISSILEKILL 1024
-/// Has support capabilities. powerplants and sutch.
-#define TFL_TURRCAPS_SUPPORT 2048
-/// Proveides at least one type of ammmo
-#define TFL_TURRCAPS_AMMOSOURCE 4096
-/// Can recive targets from external sources
-#define TFL_TURRCAPS_RECIVETARGETS 8192
-/// Capable of self-transport
-#define TFL_TURRCAPS_MOVE 16384
-/// Will roam arround even if not chasing anyting
-#define TFL_TURRCAPS_ROAM 32768
-#define TFL_TURRCAPS_HEADATTACHED 65536
-
-/// Ammo types needed and/or provided
-.float ammo_flags;
-/// Has and needs no ammo
-#define TFL_AMMO_NONE 64
-/// Uses power
-#define TFL_AMMO_ENERGY 2
-/// Uses bullets
-#define TFL_AMMO_BULLETS 4
-/// Uses explosives
-#define TFL_AMMO_ROCKETS 8
-/// Regenerates ammo on its own
-#define TFL_AMMO_RECHARGE 16
-/// Can recive ammo from others
-#define TFL_AMMO_RECIVE 32
-
-/// How incomming damage is handeld
-.float damage_flags;
-/// Cant be hurt
-#define TFL_DMG_NO 256
-/// Can be damaged
-#define TFL_DMG_YES 2
-/// Can be damaged by teammates
-#define TFL_DMG_TAKEFROMTEAM 4
-/// Traget attackers
-#define TFL_DMG_RETALIATE 8
-/// Target attackers, even is on own team
-#define TFL_DMG_RETALIATEONTEAM 16
-/// Loses target when damaged
-#define TFL_DMG_TARGETLOSS 32
-/// Reciving damage trows off aim (pointless atm, aim gets recalculated to fast). not implemented.
-#define TFL_DMG_AIMSHAKE 64
-/// Reciving damage slaps the head arround
-#define TFL_DMG_HEADSHAKE 128
-/// Die and stay dead.
-#define TFL_DMG_DEATH_NORESPAWN 256
-/// Supress std turret gibs on death
-#define TFL_DMG_DEATH_NOGIBS 512
-
-// Spawnflags
-/// Spawn in teambased modes
-#define TFL_SPAWN_TEAM 2
-/// Spawn in FFA modes
-#define TFL_SPAWN_FFA 4
-
-
-/*
-* Fields used by turrets
-*/
-/// Turrets internal ai speed
-.float ticrate;
-
-/// Where to point the when no target
-.vector idle_aim;
-
-/// Top part of turret
-.entity tur_head;
-
-/// Start/respawn health
-.float tur_health;
-
-/// Defend this entity (or ratehr this entitys position)
-.entity tur_defend;
-
-/// on/off toggle.
-.float tur_active;
-
-// Aim from this point,
-//.vector tur_aimorg;
-
-/// and shoot from here. (can be non constant, think MLRS)
-.vector tur_shotorg;
-
-/// Aim at this spot
-.vector tur_aimpos;
-
-/// Predicted time the round will impact
-.float tur_impacttime;
-
-// Predicted place the round will impact
-//.vector tur_impactpoint; // unused
-
-/// What entity the aimtrace hit, if any.
-.entity tur_impactent;
-
-/// Distance to enemy
-.float tur_dist_enemy;
-
-/// Distance to aimspot
-.float tur_dist_aimpos;
-
-/// Distance impact<->aim
-.float tur_dist_impact_to_aimpos;
-
-/// Decresment counter form .shot_volly to 0.
-.float volly_counter;
-
-/*
-* Projectile/missile. its up to the individual turret implementation to
-** deal the damage, blow upp the missile or whatever.
-*/
-/// Track then refireing is possible
-//.float attack_finished; = attack_finished_single
-/// Shoot this often
-.float shot_refire;
-/// Shots travel this fast, when appliable
-.float shot_speed;
-/// Inaccuracy
-.float shot_spread;
-/// Estimated (core) damage of projectiles. also reduce on ammo with this amount when fiering
-.float shot_dmg;
-/// If radius dmg, this is how big that radius is.
-.float shot_radius;
-/// Max force exserted by round impact
-.float shot_force;
-/// < 1 = shoot # times at target (if possible)
-.float shot_volly;
-/// Refire after a compleated volly.
-.float shot_volly_refire;
-
-/// Consider targets within this range
-.float target_range;
-/// Dont consider targets closer then
-.float target_range_min;
-// Engage fire routine on targets within
-//.float target_range_fire; // no practical use aymore, work with target_range insted.
-/// Targets closer to this are prefered
-.float target_range_optimal;
-
-/*
-* The standard targetselection tries to select a target based on
-* range, angle offset, target type, "is old target"
-* Thise biases will allow score scaling to (dis)favor diffrent targets
-*/
-/// (dis)Favor best range this mutch
-.float target_select_rangebias;
-/// (dis)Favor targeting my old enemy this mutch
-.float target_select_samebias;
-/// (dis)Favor targeting the enemy closest to my guns current angle this mutch
-.float target_select_anglebias;
-/// (dis)Favor Missiles? (-1 to diable targeting compleatly)
-.float target_select_missilebias;
-/// (dis)Favot living players (-1 to diable targeting compleatly)
-.float target_select_playerbias;
-/// Field of view
-//.float target_select_fov;
-/// Last thimestamp this surret aquierd a valid target
-.float target_select_time;
-
-/*
-* Aim refers to real aiming, not gun pos (thats done by track)
-*/
-/// Maximum offset between impact and aim spot to fire
-.float aim_firetolerance_dist;
-// Maximum angular offset between head and aimspot to fire
-//.float aim_firetolerance_angle;
-/// How fast can i rotate/pitch (per second in stepmotor mode, base force in smooth modes)
-.float aim_speed;
-/// cant aim higher/lower then this
-.float aim_maxpitch;
-/// I cant rotate more then this
-.float aim_maxrot;
-
-// Ammo/power. keeping dmg and ammo on a one to one ratio is preferable (for rating)
-/// Staring & current ammo
-.float ammo;
-/// Regenerate this mutch ammo (per second)
-.float ammo_recharge;
-/// Max amount of ammo i can hold
-.float ammo_max;
-
-
-// Uncomment below to enable various debug output.
-//#define TURRET_DEBUG
-//#define TURRET_DEBUG_TARGETVALIDATE
-//#define TURRET_DEBUG_TARGETSELECT
-
-#ifdef TURRET_DEBUG
-.float tur_dbg_dmg_t_h; // Total dmg that hit something (can be more then tur_dbg_dmg_t_f since it should count radius dmg.
-.float tur_dbg_dmg_t_f; // Total damage spent
-.float tur_dbg_start; // When did i go online?
-.float tur_dbg_tmr1; // timer for random use
-.float tur_dbg_tmr2; // timer for random use
-.float tur_dbg_tmr3; // timer for random use
-.vector tur_dbg_rvec; // Random vector, mainly for coloruing stuff'
-#endif
-
-// System main's
-/// Main AI loop
-void turret_think();
-/// Prefire checks and sutch
-void turret_fire();
-
-// Callbacks
-/// implements the actual fiering
-.void() turret_firefunc;
-/// prefire checks go here. return 1 to go bang, 0 not to.
-.float() turret_firecheckfunc;
-// Execure BEFORE main ai loop. return 0 to cancel any following proccessing.
-//.float() turret_prethink;
-/// Execure AFTER main AI loop
-.void() turret_postthink;
-
-/// Add a target
-.float(entity e_target,entity e_sender) turret_addtarget;
-
-//.float call_diehook;
-//.float call_respwnhook;
-.void() turret_diehook;
-.void() turret_respawnhook;
-
-/*
-#define TEH_THINK 2
-#define TEH_DAMAGE 4
-#define TEH_DIE 8
-#define TEH_RESPAWN 16
-#define TEH_TRACK 32
-#define TEH_AIM 64
-#define TEH_SELECT 128
-.float(float event_id) turret_eventhook;
-*/
-
-/*
-* Some turrets need other aimsystems then other.
-* This should return the place to aim at, not acctualy turn or
-* pitch anyting.
-*
-* use turret_stdproc_aim* or Make your own.
-* Make sure you update tur_enemy_dist and tur_enemy_adist
-* with the apropriate info, if you do.
-
-removed.
-*/
-// function used to aim, usualy turret_stdproc_aim_generic
-//.vector() turret_aim;
-
-/*
-* This is where the acctual turret turning should take place
-* Use turret_stdproc_track or make your own.
-wkacked to save mem.
-*/
-// Function used to turn and pitch the .tur_head usualy turret_stdproc_track
-//.void() turret_track;
-
-/*
-* Target selection, preferably but not nessesarely
-* return a normalized result.
-*/
-/// Function to use for target evaluation. usualy turret_stdproc_targetscore_generic
-.float(entity e_turret, entity e_target) turret_score_target;
-
-/*
-* Damage, death and respawn.
-*/
-//void turret_gibs_precash();
-// generalized so save mem (on fields)
-// Function to handle incomming damage. usualy turret_stdproc_damage
-//.void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) turret_damagefunc;
-// Function to handle the event of death. usualy turret_stdproc_die
-//.void() turret_diefunc;
-// Function that handles rebirth. usualy turret_stdproc_respawn
-//.void() turret_spawnfunc;
-
-/*
-* Stuff to plug into requierd but unused callbacks.
-*/
-/// Always return 1
-//float turret_stdproc_true();
-/// Always return 0
-//float turret_stdproc_false();
-/// Always return nothing at all
-//void turret_stdproc_nothing();
-
-/*
-* Target selection
-*/
-// noting uses the following atm.
-// "closeer is beter" selection
-//float turret_stdproc_targetscore_close(entity e_turret, entity e_target);
-// "further is beter" selection
-//float turret_stdproc_targetscore_far(entity e_turret, entity e_target);
-// only target_range_optimal
-//float turret_stdproc_targetscore_optimal(entity e_turret, entity e_target);
-// defendpos
-//float turret_stdproc_targetscore_defend(entity e_turret, entity e_target);
-/// Generic fairly smart bias-aware target selection.
-float turret_stdproc_targetscore_generic(entity e_turret, entity e_target);
-/// Experimental supportunits targetselector
-float turret_stdproc_targetscore_support(entity e_turret,entity e_target);
-
-/*
-* Aim functions
-*/
-/// Generic aimer guided by self.aim_flags
-vector turret_stdproc_aim_generic()
-// Straight line, current location
-//vector turret_stdproc_aim_simple()
-
-/*
-* Turret turning & pitch
-*/
-/// Tries to line up the turret head with the aimpos
-void turret_stdproc_track();
-
-/// Generic damage handeling. blows up the turret when health <= 0
-void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce);
-/// Spawns a explotion, does some damage & trows bits arround.
-void turret_stdproc_die();
-/// reassembles the turret.
-void turret_stdproc_respawn();
-
-/// Evaluate target validity
-float turret_validate_target(entity e_turret,entity e_target,float validate_flags);
-/// Turret Head Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
-vector tvt_thadv;
-/// Turret Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
-vector tvt_tadv;
-/// Turret Head Angle Diff Float. updated by a sucsessfull call to turret_validate_target
-float tvt_thadf;
-/// Turret Angle Diff Float. updated by a sucsessfull call to turret_validate_target
-float tvt_tadf;
-/// Distance. updated by a sucsessfull call to turret_validate_target
-float tvt_dist;
-
-/// updates aim org, shot org, shot dir and enemy org for selected turret
-void turret_do_updates(entity e_turret);
-//.vector tur_aimorg_updated; // creates to much aim issues. using tur_shotorg_updated insted.
-//.vector tur_shotorg_updated; // DP8815 fixes gettaginfo, no longer needed.
-.vector tur_shotdir_updated;
-
-void turrets_precash();
-
-
-
-#endif // TTURRETS_ENABLED
-
-
+// Comment out below to skip turrets
+#define TTURRETS_ENABLED
+
+#ifdef TTURRETS_ENABLED
+
+#message "with tZork turrets"
+
+vector real_origin(entity ent);
+
+/// Map time control over pain inflicted
+.float turret_scale_damage;
+/// Map time control targetting range
+.float turret_scale_range;
+/// Map time control refire
+.float turret_scale_refire;
+/// Map time control ammo held and recharged
+.float turret_scale_ammo;
+/// Map time control aim speed
+.float turret_scale_aim;
+/// Map time control health
+.float turret_scale_health;
+/// Map time control respawn time
+.float turret_scale_respawn;
+
+/// Used for cvar reloading
+.string cvar_basename;
+
+//.float spawnflags
+/// Spawn a pillar model under the turret to make it look ok on uneven ground surfaces
+#define TSF_TERRAINBASE 2
+/// Disable builtin ammo regeneration
+#define TSF_NO_AMMO_REGEN 4
+/// Dont break path to chase enemys. will still fire at them if possible.
+#define TSF_NO_PATHBREAK 8
+/// Dont respawn
+#define TSL_NO_RESPAWN 16
+
+/// target selection flags
+.float target_select_flags;
+/// target validatoin flags
+.float target_validate_flags;
+/// Dont select a target on its own.
+#define TFL_TARGETSELECT_NO 2
+/// Need line of sight
+#define TFL_TARGETSELECT_LOS 4
+/// Players are valid targets
+#define TFL_TARGETSELECT_PLAYERS 8
+/// Missiles are valid targets
+#define TFL_TARGETSELECT_MISSILES 16
+/// Responds to turret_trigger_target events
+#define TFL_TARGETSELECT_TRIGGERTARGET 32
+/// Angular limitations of turret head limits target selection
+#define TFL_TARGETSELECT_ANGLELIMITS 64
+/// Range limits apply in targetselection
+#define TFL_TARGETSELECT_RANGELIMTS 128
+/// DOnt select targets with a .team matching its own
+#define TFL_TARGETSELECT_TEAMCHECK 256
+/// Cant select targets on its own. needs to be triggerd or slaved.
+#define TFL_TARGETSELECT_NOBUILTIN 512
+/// TFL_TARGETSELECT_TEAMCHECK is inverted (selects only mebers of own .team)
+#define TFL_TARGETSELECT_OWNTEAM 1024
+/// Turrets aren't valid targets
+#define TFL_TARGETSELECT_NOTURRETS 2048
+/// Use feild of view
+#define TFL_TARGETSELECT_FOV 4096
+
+/// aim flags
+.float aim_flags;
+/// Dont aim.
+#define TFL_AIM_NO 1
+/// Go for ground, not direct hit
+#define TFL_AIM_GROUND 2
+/// Go for ground, not direct hit, but only if target is on ground.
+#define TFL_AIM_GROUND2 4
+/// Use balistic aim. FIXME: not implemented
+#define TFL_AIM_BALISTIC 8
+/// Try to predict target movement (does not account for gravity)
+#define TFL_AIM_LEAD 16
+/// Compensate for shot traveltime when lead
+#define TFL_AIM_SHOTTIMECOMPENSATE 32
+/// Aim slightly in front of target
+#define TFL_AIM_INFRONT 64
+/// Aim slightly behind target
+#define TFL_AIM_BEHIND 128
+/// blend real and predicted z positions. (fake bounce prediction)
+#define TFL_AIM_ZEASE 256
+/// Try to do real prediction of targets z pos at impact.
+#define TFL_AIM_ZPREDICT 512
+/// Simply aim at target's current location
+#define TFL_AIM_SIMPLE 1024
+
+/// track (turn and pitch head) flags
+.float track_flags;
+/// Dont move head
+#define TFL_TRACK_NO 2
+/// Pitch the head
+#define TFL_TRACK_PITCH 4
+/// Rotate the head
+#define TFL_TRACK_ROT 8
+
+/// How tracking is preformed
+.float track_type;
+/// Hard angle increments. Ugly for fast turning, best accuracy.
+#define TFL_TRACKTYPE_STEPMOTOR 1
+/// Smoth absolute movement. Looks ok, fair accuracy.
+#define TFL_TRACKTYPE_FLUIDPRECISE 2
+/// Simulated inertia. "Wobbly mode" Looks kool, can mean really bad accuracy depending on how the feilds below are set
+#define TFL_TRACKTYPE_FLUIDINERTIA 3
+/// TFL_TRACKTYPE_FLUIDINERTIA: pitch multiplier
+.float track_accel_pitch;
+/// TFL_TRACKTYPE_FLUIDINERTIA: rotation multiplier
+.float track_accel_rot;
+/// TFL_TRACKTYPE_FLUIDINERTIA: Blendrate with old rotation (inertia simulation) 1 = only old, 0 = only new
+.float track_blendrate;
+
+/// How prefire check is preformed
+.float firecheck_flags;
+/// Dont kill the world
+#define TFL_FIRECHECK_WORLD 2
+/// Dont kill the dead
+#define TFL_FIRECHECK_DEAD 4
+/// Range limits apply
+#define TFL_FIRECHECK_DISTANCES 8
+/// Line Of Sight needs to be clear
+#define TFL_FIRECHECK_LOS 16
+/// Consider distance inpactpoint<->aimspot
+#define TFL_FIRECHECK_AIMDIST 32
+/// Consider enemy origin<->impactpoint
+#define TFL_FIRECHECK_REALDIST 64
+/// Consider angular diff head<->aimspot
+#define TFL_FIRECHECK_ANGLEDIST 128
+/// (re)consider target.team<->self.team
+#define TFL_FIRECHECK_TEAMCECK 256
+/// Try to avoid friendly fire
+#define TFL_FIRECHECK_AFF 512
+/// Own .ammo needs to be >= then own .shot_dmg
+#define TFL_FIRECHECK_OWM_AMMO 1024
+/// Others ammo need to be < others .ammo_max
+#define TFL_FIRECHECK_OTHER_AMMO 2048
+/// Check own .attack_finished_single vs time
+#define TFL_FIRECHECK_REFIRE 4096
+/// Move the acctual target to aimspot before tracing impact (and back after)
+#define TFL_FIRECHECK_VERIFIED 8192
+/// Dont do any chekcs
+#define TFL_FIRECHECK_NO 16384
+
+/// How shooting is done
+.float shoot_flags;
+/// Dont shoot
+#define TFL_SHOOT_NO 64
+/// Fire in vollys (partial implementation through .shot_volly)
+#define TFL_SHOOT_VOLLY 2
+/// Always do a full volly, even if target is lost or dead. (not implemented)
+#define TFL_SHOOT_VOLLYALWAYS 4
+/// Loop though all valid tarters, and hit them.
+#define TFL_SHOOT_HITALLVALID 8
+/// Fiering makes unit loose target (after volly is done, if in volly mode)
+#define TFL_SHOOT_CLEARTARGET 16
+///Custom shooting;
+#define TFL_SHOOT_CUSTOM 32
+
+/// Information aboute the units capabilities
+.float turrcaps_flags;
+/// No kown capabilities
+#define TFL_TURRCAPS_NONE 0
+/// Capable of sniping
+#define TFL_TURRCAPS_SNIPER 2
+/// Capable of splasdamage
+#define TFL_TURRCAPS_RADIUSDMG 4
+/// Has one or more cannons with zero shot traveltime
+#define TFL_TURRCAPS_HITSCAN 8
+/// More then one (type of) gun
+#define TFL_TURRCAPS_MULTIGUN 16
+/// Carries at least one guided weapon
+#define TFL_TURRCAPS_GUIDED 32
+/// At least one gun fiers slow projectiles
+#define TFL_TURRCAPS_SLOWPROJ 64
+/// At least one gun fiers medium speed projectiles
+#define TFL_TURRCAPS_MEDPROJ 128
+/// At least one gun fiers fast projectiles
+#define TFL_TURRCAPS_FASTPROJ 256
+/// At least one gun capable of damaging players
+#define TFL_TURRCAPS_PLAYERKILL 512
+/// At least one gun that can shoot town missiles
+#define TFL_TURRCAPS_MISSILEKILL 1024
+/// Has support capabilities. powerplants and sutch.
+#define TFL_TURRCAPS_SUPPORT 2048
+/// Proveides at least one type of ammmo
+#define TFL_TURRCAPS_AMMOSOURCE 4096
+/// Can recive targets from external sources
+#define TFL_TURRCAPS_RECIVETARGETS 8192
+/// Capable of self-transport
+#define TFL_TURRCAPS_MOVE 16384
+/// Will roam arround even if not chasing anyting
+#define TFL_TURRCAPS_ROAM 32768
+#define TFL_TURRCAPS_HEADATTACHED 65536
+
+/// Ammo types needed and/or provided
+.float ammo_flags;
+/// Has and needs no ammo
+#define TFL_AMMO_NONE 64
+/// Uses power
+#define TFL_AMMO_ENERGY 2
+/// Uses bullets
+#define TFL_AMMO_BULLETS 4
+/// Uses explosives
+#define TFL_AMMO_ROCKETS 8
+/// Regenerates ammo on its own
+#define TFL_AMMO_RECHARGE 16
+/// Can recive ammo from others
+#define TFL_AMMO_RECIVE 32
+
+/// How incomming damage is handeld
+.float damage_flags;
+/// Cant be hurt
+#define TFL_DMG_NO 256
+/// Can be damaged
+#define TFL_DMG_YES 2
+/// Can be damaged by teammates
+#define TFL_DMG_TAKEFROMTEAM 4
+/// Traget attackers
+#define TFL_DMG_RETALIATE 8
+/// Target attackers, even is on own team
+#define TFL_DMG_RETALIATEONTEAM 16
+/// Loses target when damaged
+#define TFL_DMG_TARGETLOSS 32
+/// Reciving damage trows off aim (pointless atm, aim gets recalculated to fast). not implemented.
+#define TFL_DMG_AIMSHAKE 64
+/// Reciving damage slaps the head arround
+#define TFL_DMG_HEADSHAKE 128
+/// Die and stay dead.
+#define TFL_DMG_DEATH_NORESPAWN 256
+/// Supress std turret gibs on death
+#define TFL_DMG_DEATH_NOGIBS 512
+
+// Spawnflags
+/// Spawn in teambased modes
+#define TFL_SPAWN_TEAM 2
+/// Spawn in FFA modes
+#define TFL_SPAWN_FFA 4
+
+
+/*
+* Fields used by turrets
+*/
+/// Turrets internal ai speed
+.float ticrate;
+
+/// Where to point the when no target
+.vector idle_aim;
+
+/// Top part of turret
+.entity tur_head;
+
+/// Start/respawn health
+.float tur_health;
+
+/// Defend this entity (or ratehr this entitys position)
+.entity tur_defend;
+
+/// on/off toggle.
+.float tur_active;
+
+// Aim from this point,
+//.vector tur_aimorg;
+
+/// and shoot from here. (can be non constant, think MLRS)
+.vector tur_shotorg;
+
+/// Aim at this spot
+.vector tur_aimpos;
+
+/// Predicted time the round will impact
+.float tur_impacttime;
+
+// Predicted place the round will impact
+//.vector tur_impactpoint; // unused
+
+/// What entity the aimtrace hit, if any.
+.entity tur_impactent;
+
+/// Distance to enemy
+.float tur_dist_enemy;
+
+/// Distance to aimspot
+.float tur_dist_aimpos;
+
+/// Distance impact<->aim
+.float tur_dist_impact_to_aimpos;
+
+/// Decresment counter form .shot_volly to 0.
+.float volly_counter;
+
+/*
+* Projectile/missile. its up to the individual turret implementation to
+** deal the damage, blow upp the missile or whatever.
+*/
+/// Track then refireing is possible
+//.float attack_finished; = attack_finished_single
+/// Shoot this often
+.float shot_refire;
+/// Shots travel this fast, when appliable
+.float shot_speed;
+/// Inaccuracy
+.float shot_spread;
+/// Estimated (core) damage of projectiles. also reduce on ammo with this amount when fiering
+.float shot_dmg;
+/// If radius dmg, this is how big that radius is.
+.float shot_radius;
+/// Max force exserted by round impact
+.float shot_force;
+/// < 1 = shoot # times at target (if possible)
+.float shot_volly;
+/// Refire after a compleated volly.
+.float shot_volly_refire;
+
+/// Consider targets within this range
+.float target_range;
+/// Dont consider targets closer then
+.float target_range_min;
+// Engage fire routine on targets within
+//.float target_range_fire; // no practical use aymore, work with target_range insted.
+/// Targets closer to this are prefered
+.float target_range_optimal;
+
+/*
+* The standard targetselection tries to select a target based on
+* range, angle offset, target type, "is old target"
+* Thise biases will allow score scaling to (dis)favor diffrent targets
+*/
+/// (dis)Favor best range this mutch
+.float target_select_rangebias;
+/// (dis)Favor targeting my old enemy this mutch
+.float target_select_samebias;
+/// (dis)Favor targeting the enemy closest to my guns current angle this mutch
+.float target_select_anglebias;
+/// (dis)Favor Missiles? (-1 to diable targeting compleatly)
+.float target_select_missilebias;
+/// (dis)Favot living players (-1 to diable targeting compleatly)
+.float target_select_playerbias;
+/// Field of view
+//.float target_select_fov;
+/// Last thimestamp this surret aquierd a valid target
+.float target_select_time;
+
+/*
+* Aim refers to real aiming, not gun pos (thats done by track)
+*/
+/// Maximum offset between impact and aim spot to fire
+.float aim_firetolerance_dist;
+// Maximum angular offset between head and aimspot to fire
+//.float aim_firetolerance_angle;
+/// How fast can i rotate/pitch (per second in stepmotor mode, base force in smooth modes)
+.float aim_speed;
+/// cant aim higher/lower then this
+.float aim_maxpitch;
+/// I cant rotate more then this
+.float aim_maxrot;
+
+// Ammo/power. keeping dmg and ammo on a one to one ratio is preferable (for rating)
+/// Staring & current ammo
+.float ammo;
+/// Regenerate this mutch ammo (per second)
+.float ammo_recharge;
+/// Max amount of ammo i can hold
+.float ammo_max;
+
+
+// Uncomment below to enable various debug output.
+//#define TURRET_DEBUG
+//#define TURRET_DEBUG_TARGETVALIDATE
+//#define TURRET_DEBUG_TARGETSELECT
+
+#ifdef TURRET_DEBUG
+.float tur_dbg_dmg_t_h; // Total dmg that hit something (can be more then tur_dbg_dmg_t_f since it should count radius dmg.
+.float tur_dbg_dmg_t_f; // Total damage spent
+.float tur_dbg_start; // When did i go online?
+.float tur_dbg_tmr1; // timer for random use
+.float tur_dbg_tmr2; // timer for random use
+.float tur_dbg_tmr3; // timer for random use
+.vector tur_dbg_rvec; // Random vector, mainly for coloruing stuff'
+#endif
+
+// System main's
+/// Main AI loop
+void turret_think();
+/// Prefire checks and sutch
+void turret_fire();
+
+// Callbacks
+/// implements the actual fiering
+.void() turret_firefunc;
+/// prefire checks go here. return 1 to go bang, 0 not to.
+.float() turret_firecheckfunc;
+// Execure BEFORE main ai loop. return 0 to cancel any following proccessing.
+//.float() turret_prethink;
+/// Execure AFTER main AI loop
+.void() turret_postthink;
+
+/// Add a target
+.float(entity e_target,entity e_sender) turret_addtarget;
+
+//.float call_diehook;
+//.float call_respwnhook;
+.void() turret_diehook;
+.void() turret_respawnhook;
+
+/*
+#define TEH_THINK 2
+#define TEH_DAMAGE 4
+#define TEH_DIE 8
+#define TEH_RESPAWN 16
+#define TEH_TRACK 32
+#define TEH_AIM 64
+#define TEH_SELECT 128
+.float(float event_id) turret_eventhook;
+*/
+
+/*
+* Some turrets need other aimsystems then other.
+* This should return the place to aim at, not acctualy turn or
+* pitch anyting.
+*
+* use turret_stdproc_aim* or Make your own.
+* Make sure you update tur_enemy_dist and tur_enemy_adist
+* with the apropriate info, if you do.
+
+removed.
+*/
+// function used to aim, usualy turret_stdproc_aim_generic
+//.vector() turret_aim;
+
+/*
+* This is where the acctual turret turning should take place
+* Use turret_stdproc_track or make your own.
+wkacked to save mem.
+*/
+// Function used to turn and pitch the .tur_head usualy turret_stdproc_track
+//.void() turret_track;
+
+/*
+* Target selection, preferably but not nessesarely
+* return a normalized result.
+*/
+/// Function to use for target evaluation. usualy turret_stdproc_targetscore_generic
+.float(entity e_turret, entity e_target) turret_score_target;
+
+/*
+* Damage, death and respawn.
+*/
+//void turret_gibs_precash();
+// generalized so save mem (on fields)
+// Function to handle incomming damage. usualy turret_stdproc_damage
+//.void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) turret_damagefunc;
+// Function to handle the event of death. usualy turret_stdproc_die
+//.void() turret_diefunc;
+// Function that handles rebirth. usualy turret_stdproc_respawn
+//.void() turret_spawnfunc;
+
+/*
+* Stuff to plug into requierd but unused callbacks.
+*/
+/// Always return 1
+//float turret_stdproc_true();
+/// Always return 0
+//float turret_stdproc_false();
+/// Always return nothing at all
+//void turret_stdproc_nothing();
+
+/*
+* Target selection
+*/
+// noting uses the following atm.
+// "closeer is beter" selection
+//float turret_stdproc_targetscore_close(entity e_turret, entity e_target);
+// "further is beter" selection
+//float turret_stdproc_targetscore_far(entity e_turret, entity e_target);
+// only target_range_optimal
+//float turret_stdproc_targetscore_optimal(entity e_turret, entity e_target);
+// defendpos
+//float turret_stdproc_targetscore_defend(entity e_turret, entity e_target);
+/// Generic fairly smart bias-aware target selection.
+float turret_stdproc_targetscore_generic(entity e_turret, entity e_target);
+/// Experimental supportunits targetselector
+float turret_stdproc_targetscore_support(entity e_turret,entity e_target);
+
+/*
+* Aim functions
+*/
+/// Generic aimer guided by self.aim_flags
+vector turret_stdproc_aim_generic()
+// Straight line, current location
+//vector turret_stdproc_aim_simple()
+
+/*
+* Turret turning & pitch
+*/
+/// Tries to line up the turret head with the aimpos
+void turret_stdproc_track();
+
+/// Generic damage handeling. blows up the turret when health <= 0
+void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce);
+/// Spawns a explotion, does some damage & trows bits arround.
+void turret_stdproc_die();
+/// reassembles the turret.
+void turret_stdproc_respawn();
+
+/// Evaluate target validity
+float turret_validate_target(entity e_turret,entity e_target,float validate_flags);
+/// Turret Head Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
+vector tvt_thadv;
+/// Turret Angle Diff Vector. updated by a sucsessfull call to turret_validate_target
+vector tvt_tadv;
+/// Turret Head Angle Diff Float. updated by a sucsessfull call to turret_validate_target
+float tvt_thadf;
+/// Turret Angle Diff Float. updated by a sucsessfull call to turret_validate_target
+float tvt_tadf;
+/// Distance. updated by a sucsessfull call to turret_validate_target
+float tvt_dist;
+
+/// updates aim org, shot org, shot dir and enemy org for selected turret
+void turret_do_updates(entity e_turret);
+//.vector tur_aimorg_updated; // creates to much aim issues. using tur_shotorg_updated insted.
+//.vector tur_shotorg_updated; // DP8815 fixes gettaginfo, no longer needed.
+.vector tur_shotdir_updated;
+
+void turrets_precash();
+
+
+
+#endif // TTURRETS_ENABLED
+
+
Property changes on: trunk/data/qcsrc/server/tturrets/include/turrets_early.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/system/system_aimprocs.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/system/system_aimprocs.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/system/system_aimprocs.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,122 +1,122 @@
-/*
-* Generic aim
-
-supports:
-TFL_AIM_NO
-TFL_AIM_GROUND
-TFL_AIM_LEAD
-TFL_AIM_SHOTTIMECOMPENSATE
-TFL_AIM_INFRONT
-TFL_AIM_BEHIND
-TFL_AIM_ZEASE
-
-not supported:
-TFL_AIM_BALISTIC
-*/
-vector turret_stdproc_aim_generic()
-{
-
- vector pre_pos,prep;
- float distance,impact_time,i,mintime;
-
- turret_tag_fire_update();
-
- if(self.aim_flags & TFL_AIM_SIMPLE)
- return real_origin(self.enemy);
-
- // Keep track of when we can shoot the next time and
- // try to predict where the target will be then, so we can put our aimpoint there.
- // + sys_ticrate for non hitscan, becouse spawned
- // projectiles dont move during the first tic of their life.
- if (self.turrcaps_flags & TFL_TURRCAPS_HITSCAN)
- mintime = max(self.attack_finished_single - time,0);
- else
- mintime = max(self.attack_finished_single - time,0) + sys_ticrate;
-
- // Baseline
- pre_pos = real_origin(self.enemy);// + (self.enemy.velocity * mintime);
-
- if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target
- pre_pos = pre_pos + (normalize(self.enemy.velocity) * 64);
-
- if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target
- pre_pos = pre_pos - (normalize(self.enemy.velocity) * 32);
-
- // Lead?
- if (self.aim_flags & TFL_AIM_LEAD)
- if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
- {
- // FIXME: this cant be the best way to do this..
-
-
- prep = pre_pos;
- 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;
- }
-
-
- // tnx to Rudolf "div0" Polzer for this solution.
- // hmm tobad it dont work.
- /*
- vector q;
- q = solve_quadratic(self.enemy.velocity*self.enemy.velocity - self.shot_speed*self.shot_speed, 2*(pre_pos*self.enemy.velocity), pre_pos * pre_pos);
- if(q_x > 0)
- impact_time = q_x;
- else
- impact_time = q_y;
- */
-
- prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
-
- if(self.aim_flags & TFL_AIM_ZPREDICT)
- if not(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_ticrate)
- {
- vz = vz - (sv_gravity * sys_ticrate);
- prep_z = prep_z + vz * sys_ticrate;
- }
- }
-
-
- pre_pos = prep;
- }
- else
- pre_pos = pre_pos + self.enemy.velocity * mintime;
-
- // Smooth out predict-Z?
- /*
- if (self.aim_flags & TFL_AIM_ZEASE)
- if (self.enemy.flags & FL_CLIENT)
- {
- vector v;
- v = real_origin(self.enemy);
- pre_pos_z = (pre_pos_z + v_z) * 0.5;
- }
- */
-
- if(self.aim_flags & TFL_AIM_GROUND2)
- {
- tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
- if(trace_fraction != 1.0)
- pre_pos = trace_endpos;
- }
-
- /*
- // This turret should hit the ground neer a target rather the do a direct hit
- if (self.aim_flags & TFL_AIM_GROUND)
- {
- traceline(pre_pos + '0 0 8',pre_pos - '0 0 10000',MOVE_WORLDONLY,self.enemy);
- pre_pos = trace_endpos;
- }
- */
-
- return pre_pos;
-}
+/*
+* Generic aim
+
+supports:
+TFL_AIM_NO
+TFL_AIM_GROUND
+TFL_AIM_LEAD
+TFL_AIM_SHOTTIMECOMPENSATE
+TFL_AIM_INFRONT
+TFL_AIM_BEHIND
+TFL_AIM_ZEASE
+
+not supported:
+TFL_AIM_BALISTIC
+*/
+vector turret_stdproc_aim_generic()
+{
+
+ vector pre_pos,prep;
+ float distance,impact_time,i,mintime;
+
+ turret_tag_fire_update();
+
+ if(self.aim_flags & TFL_AIM_SIMPLE)
+ return real_origin(self.enemy);
+
+ // Keep track of when we can shoot the next time and
+ // try to predict where the target will be then, so we can put our aimpoint there.
+ // + sys_ticrate for non hitscan, becouse spawned
+ // projectiles dont move during the first tic of their life.
+ if (self.turrcaps_flags & TFL_TURRCAPS_HITSCAN)
+ mintime = max(self.attack_finished_single - time,0);
+ else
+ mintime = max(self.attack_finished_single - time,0) + sys_ticrate;
+
+ // Baseline
+ pre_pos = real_origin(self.enemy);// + (self.enemy.velocity * mintime);
+
+ if (self.aim_flags & TFL_AIM_INFRONT) // Aim a bit in front of the target
+ pre_pos = pre_pos + (normalize(self.enemy.velocity) * 64);
+
+ if (self.aim_flags & TFL_AIM_BEHIND) // Aim a bit behind the target
+ pre_pos = pre_pos - (normalize(self.enemy.velocity) * 32);
+
+ // Lead?
+ if (self.aim_flags & TFL_AIM_LEAD)
+ if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
+ {
+ // FIXME: this cant be the best way to do this..
+
+
+ prep = pre_pos;
+ 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;
+ }
+
+
+ // tnx to Rudolf "div0" Polzer for this solution.
+ // hmm tobad it dont work.
+ /*
+ vector q;
+ q = solve_quadratic(self.enemy.velocity*self.enemy.velocity - self.shot_speed*self.shot_speed, 2*(pre_pos*self.enemy.velocity), pre_pos * pre_pos);
+ if(q_x > 0)
+ impact_time = q_x;
+ else
+ impact_time = q_y;
+ */
+
+ prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
+
+ if(self.aim_flags & TFL_AIM_ZPREDICT)
+ if not(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_ticrate)
+ {
+ vz = vz - (sv_gravity * sys_ticrate);
+ prep_z = prep_z + vz * sys_ticrate;
+ }
+ }
+
+
+ pre_pos = prep;
+ }
+ else
+ pre_pos = pre_pos + self.enemy.velocity * mintime;
+
+ // Smooth out predict-Z?
+ /*
+ if (self.aim_flags & TFL_AIM_ZEASE)
+ if (self.enemy.flags & FL_CLIENT)
+ {
+ vector v;
+ v = real_origin(self.enemy);
+ pre_pos_z = (pre_pos_z + v_z) * 0.5;
+ }
+ */
+
+ if(self.aim_flags & TFL_AIM_GROUND2)
+ {
+ tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
+ if(trace_fraction != 1.0)
+ pre_pos = trace_endpos;
+ }
+
+ /*
+ // This turret should hit the ground neer a target rather the do a direct hit
+ if (self.aim_flags & TFL_AIM_GROUND)
+ {
+ traceline(pre_pos + '0 0 8',pre_pos - '0 0 10000',MOVE_WORLDONLY,self.enemy);
+ pre_pos = trace_endpos;
+ }
+ */
+
+ return pre_pos;
+}
Property changes on: trunk/data/qcsrc/server/tturrets/system/system_aimprocs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/system/system_main.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/system/system_main.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/system/system_main.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,1258 +1,1258 @@
-#define cvar_base "g_turrets_unit_"
-
-/*
-float turret_customizeentityforclient()
-{
-}
-
-float Turret_SendEntity(entity to, float sf)
-{
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
- WriteCoord(MSG_ENTITY, self.tur_head.angles_x);
- WriteCoord(MSG_ENTITY, self.tur_head.angles_y);
- WriteByte(MSG_ENTITY, self.tur_head.frame);
-
- //WriteCoord(MSG_ENTITY, self.tur_head.angles_z);
-
- return TRUE;
-}
-*/
-
-void load_unit_settings(entity ent,string unitname,float is_reload)
-{
- string sbase;
-
- // dprint("Reloading turret ",e_turret.netname,"\n");
-
- if (ent == world)
- return;
-
- 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';
-
- if (ent.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- ent.tur_head.angles = '0 0 0';
- else
- ent.tur_head.angles = ent.angles;
- }
-
- 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_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
- ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * 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_maxrot = 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_rot = cvar(strcat(sbase,"_track_accel_rot"));
- ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
-
- if(is_reload)
- if(ent.turret_respawnhook)
- ent.turret_respawnhook();
-
-}
-
-/*
-float turret_stdproc_true()
-{
- return 1;
-}
-
-float turret_stdproc_false()
-{
- return 0;
-}
-
-
-void turret_stdproc_nothing()
-{
- return;
-}
-*/
-
-/**
-** updates enemy distances, predicted impact point/time
-** and updated aim<->predict impact distance.
-**/
-void turret_do_updates(entity t_turret)
-{
- vector enemy_pos,oldpos;
- entity oldself;
-
- oldself = self;
- self = t_turret;
-
- enemy_pos = real_origin(self.enemy);
-
- turret_tag_fire_update();
-
- self.tur_shotdir_updated = normalize(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)
- if(self.enemy)
- {
- oldpos = self.enemy.origin;
- setorigin(self.enemy,self.tur_aimpos);
- }
-
- //dprint("NN: ", self.netname," THVN: ",self.tur_head.classname," frame:",ftos(self.tur_head.frame),"\n");
- //dprint("self.tur_shotorg: ",vtos(self.tur_shotorg),"\n");
- tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
-
- if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
- if(self.enemy)
- setorigin(self.enemy,oldpos);
-
- //self.tur_impactpoint = trace_endpos;
- self.tur_impactent = trace_ent;
- self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins)*0.5);
- self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
-
- self = oldself;
-}
-
-/*
-vector turret_fovsearch_pingpong()
-{
- vector wish_angle;
- if(self.phase < time)
- {
- if( self.tur_head.phase )
- self.tur_head.phase = 0;
- else
- self.tur_head.phase = 1;
- self.phase = time + 5;
- }
-
- if( self.tur_head.phase)
- wish_angle = self.idle_aim + '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
- else
- wish_angle = self.idle_aim - '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
-
- return wish_angle;
-}
-
-vector turret_fovsearch_steprot()
-{
- vector wish_angle;
- //float rot_add;
-
- wish_angle = self.tur_head.angles;
- wish_angle_x = self.idle_aim_x;
-
- if (self.phase < time)
- {
- //rot_add = self.aim_maxrot / self.target_select_fov;
- wish_angle_y += (self.target_select_fov * 2);
-
- if(wish_angle_y > 360)
- wish_angle_y = wish_angle_y - 360;
-
- self.phase = time + 1.5;
- }
-
- return wish_angle;
-}
-
-vector turret_fovsearch_random()
-{
- vector wish_angle;
-
- if (self.phase < time)
- {
- wish_angle_y = random() * self.aim_maxrot;
- if(random() < 0.5)
- wish_angle_y *= -1;
-
- wish_angle_x = random() * self.aim_maxpitch;
- if(random() < 0.5)
- wish_angle_x *= -1;
-
- self.phase = time + 5;
-
- self.tur_aimpos = wish_angle;
- }
-
- return self.idle_aim + self.tur_aimpos;
-}
-*/
-
-/**
-** Handles head rotation according to
-** the units .track_type and .track_flags
-**/
-//.entity aim_mark;
-void turret_stdproc_track()
-{
- vector target_angle; // This is where we want to aim
- vector move_angle; // This is where we can aim
- float f_tmp;
-
- if (self.track_flags == TFL_TRACK_NO)
- return;
-
- if(!self.tur_active)
- target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
- else if (self.enemy == world)
- {
- if(time > self.lip)
- if (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- target_angle = self.idle_aim + self.angles;
- else
- target_angle = self.idle_aim;
- else
- target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
- }
- else
- {
- // Find the direction
- target_angle = normalize(self.tur_aimpos - self.tur_shotorg);
- target_angle = vectoangles(target_angle); // And make a angle
- }
-
- self.tur_head.angles_x = safeangle(self.tur_head.angles_x);
- self.tur_head.angles_y = safeangle(self.tur_head.angles_y);
-
- // Find the diffrence between where we currently aim and where we want to aim
- vector a_off;
-
-
- if (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- {
- move_angle = target_angle - (self.angles + self.tur_head.angles);
- move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
- a_off = '0 0 0';
-
- }
- else
- {
- move_angle = target_angle - self.tur_head.angles;
- move_angle = shortangle_vxy(move_angle,self.tur_head.angles);
- a_off = self.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 + a_off_x > self.aim_maxpitch)
- self.tur_head.angles_x = a_off_x + self.aim_maxpitch;
-
- if(self.tur_head.angles_x + a_off_x < -self.aim_maxpitch)
- self.tur_head.angles_x = a_off_x - self.aim_maxpitch;
- }
-
- if (self.track_flags & TFL_TRACK_ROT)
- {
- self.tur_head.angles_y += bound(-f_tmp, move_angle_y, f_tmp);
- if((self.tur_head.angles_y - a_off_y) > self.aim_maxrot)
- self.tur_head.angles_y = a_off_y + self.aim_maxrot;
-
- if((self.tur_head.angles_y - a_off_y) < -self.aim_maxrot)
- self.tur_head.angles_y = a_off_y - self.aim_maxrot;
- }
-
- 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_rot * 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) + a_off_x > self.aim_maxpitch)
- {
- self.tur_head.avelocity_x = 0;
- self.tur_head.angles_x = a_off_x + self.aim_maxpitch;
- }
- if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) + a_off_x < -self.aim_maxpitch)
- {
- self.tur_head.avelocity_x = 0;
- self.tur_head.angles_x = a_off_x - self.aim_maxpitch;
- }
-
- }
-
- // rot
- if (self.track_flags & TFL_TRACK_ROT)
- {
- self.tur_head.avelocity_y = move_angle_y;
-
- if(((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate)- a_off_y) > self.aim_maxrot)
- {
- self.tur_head.avelocity_y = 0;
- self.tur_head.angles_y = a_off_y + self.aim_maxrot;
- }
-
- if(((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) - a_off_y) < -self.aim_maxrot)
- {
- self.tur_head.avelocity_y = 0;
- self.tur_head.angles_y = a_off_y - self.aim_maxrot;
- }
-
- }
-
-}
-
-
-/*
- + = 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_OWM_AMMO
- + TFL_FIRECHECK_OTHER_AMMO
- + TFL_FIRECHECK_REFIRE
-*/
-
-/**
-** Preforms pre-fire checks based on the uints firecheck_flags
-**/
-float turret_stdproc_firecheck()
-{
- // This one just dont care =)
- if (self.firecheck_flags & TFL_FIRECHECK_NO) return 1;
-
- // 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) && (self.volly_counter != self.shot_volly))
- 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;
-
- // Plz stop killing the world!
- if (self.firecheck_flags & TFL_FIRECHECK_WORLD)
- if (self.enemy == world) return 0;
-
- // Own ammo?
- if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO)
- if (self.ammo < self.shot_dmg) return 0;
-
- // Other's ammo? (support-supply units)
- if (self.firecheck_flags & TFL_FIRECHECK_OTHER_AMMO)
- if (self.enemy.ammo >= self.enemy.ammo_max) return 0;
-
- if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
- {
- // Not close enougth?
- //if (self.tur_dist_aimpos > self.target_range_fire) return 0;
-
- // To close?
- if (self.tur_dist_aimpos < self.target_range_min) 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)
- if (self.tur_impactent != self.enemy)
- 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;
-}
-
-/*
- + TFL_TARGETSELECT_NO
- + TFL_TARGETSELECT_LOS
- + TFL_TARGETSELECT_PLAYERS
- + TFL_TARGETSELECT_MISSILES
- - TFL_TARGETSELECT_TRIGGERTARGET
- + TFL_TARGETSELECT_ANGLELIMITS
- + TFL_TARGETSELECT_RANGELIMTS
- + TFL_TARGETSELECT_TEAMCHECK
- - TFL_TARGETSELECT_NOBUILTIN
- + TFL_TARGETSELECT_OWNTEAM
-*/
-
-/**
-** Evaluate a entity for target valitity based on validate_flags
-**/
-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(checkpvs(e_target.origin, e_turret))
- return -1;
-
- if (!e_target)// == world)
- 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.takedamage == DAMAGE_NO) || (e_target.health < 0))
- return -6;
-
- // player
- if (e_target.flags & FL_CLIENT)
- {
- if not (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.turret_firefunc || 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 (validate_flags & TFL_TARGETSELECT_MISSILES)
- return -10;
-
- // 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_RANGELIMTS)
- {
- 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?
- if(e_turret.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- {
- tvt_thadv = angleofs3(e_turret.tur_head.origin,e_turret.angles + e_turret.tur_head.angles ,e_target);
- //tvt_thadv = angleofs(e_turret.angles,e_target);
- }
- else
- {
- tvt_thadv = angleofs(e_turret.tur_head,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_maxrot)
- 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.tur_shotorg,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;
-
-#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
- float f;
-
- m_score = 0;
- if(self.enemy)
- if(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;
- }
-
- e = findradius(self.origin,self.target_range);
-
- // Nothing to aim at?
- if (!e) return world;
-
- while (e)
- {
- f = turret_validate_target(self,e,self.target_select_flags);
- 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;
-}
-
-void turret_think()
-{
- entity e;
-
- self.nextthink = time + self.ticrate;
-
- // ONS uses somewhat backwards linking.
- if (teamplay)
- {
- if not (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_stdproc_respawn();
- }
-
-
- if (cvar("g_turrets_reloadcvars") == 1)
- {
- e = nextent(world);
- while (e)
- {
- if (e.tur_head != world)
- {
-
- load_unit_settings(e,e.cvar_basename,1);
- if(e.turret_postthink)
- e.turret_postthink();
- }
-
- e = nextent(e);
- }
-
- cvar_set("g_turrets_reloadcvars","0");
- }
-
-#ifdef TURRET_DEBUG
- if (self.tur_dbg_tmr1 < time)
- {
- if (self.enemy) paint_target (self.enemy,128,self.tur_dbg_rvec,0.9);
- paint_target(self,256,self.tur_dbg_rvec,0.9);
- self.tur_dbg_tmr1 = time + 1;
- }
-#endif
-
- // Handle ammo
- if not (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.tur_active)
- {
- turret_stdproc_track();
- return;
- }
-
- //This is just wrong :|
- if(self.deadflag != DEAD_NO)
- {
- dprint("WARNING: dead turret running the think function!\n");
- 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 (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.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch?
- if (!self.track_flags & TFL_TRACK_NO)
- turret_stdproc_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.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch
- if (!self.track_flags & TFL_TRACK_NO)
- turret_stdproc_track();
-
- turret_do_updates(self);
-
- // Fire!
- if (self.turret_firecheckfunc() != 0)
- turret_fire();
-
- if(self.turret_postthink)
- self.turret_postthink();
-
- return;
- }
-
- // Check if we have a vailid enemy, and try to find one if we dont.
- if( ((self.target_select_time + cvar("g_turrets_targetscan_maxdelay")) < time)
- || (turret_validate_target(self,self.enemy,self.target_validate_flags) <= 0) )
- if not (self.target_select_time + cvar("g_turrets_targetscan_mindelay") > time)
- {
- self.enemy = turret_select_target();
- //if(self.enemy)
- self.target_select_time = time;
-
- }
-
-
- // No target, just go to idle, do any custom stuff and bail.
- if (self.enemy == world)
- {
- // Turn & pitch
- if (!self.track_flags & TFL_TRACK_NO)
- turret_stdproc_track();
-
- // do any per-turret stuff
- if(self.turret_postthink)
- self.turret_postthink();
-
- // And bail.
- return;
- }
- else
- self.lip = time + cvar("g_turrets_aimidle_delay"); // Keep track of the last time we had a target.
-
- // Predict?
- if not((self.aim_flags & TFL_AIM_NO))
- self.tur_aimpos = turret_stdproc_aim_generic();
-
- // Turn & pitch?
- if (!self.track_flags & TFL_TRACK_NO)
- turret_stdproc_track();
-
- turret_do_updates(self);
- // Fire?
- if (self.turret_firecheckfunc())
- turret_fire();
- }
-
- // do any per-turret stuff
- if(self.turret_postthink)
- self.turret_postthink();
-}
-
-void turret_fire()
-{
- if (cvar("g_turrets_nofire") != 0)
- return;
-
- if ((!self.tur_active) || (self.deadflag != DEAD_NO))
- return;
-
- self.turret_firefunc();
-
- self.attack_finished_single = time + self.shot_refire;
- self.ammo = 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_dbg_rvec, self.tur_impacttime + 0.25);
-#endif
-}
-
-void turret_stdproc_fire()
-{
- dprint("^1Bang, ^3your dead^7 ",self.enemy.netname,"! ^1(turret with no real firefunc)\n");
-}
-
-/*
- When .used a turret switch team to activator.team.
- If activator is world, the turrets goes inactive.
-*/
-void turret_stdproc_use()
-{
- dprint("Turret ",self.netname, " used by ",activator.classname,"\n");
-
- self.team = activator.team;
-
- if(self.team == 0)
- self.tur_active = 0;
- else
- self.tur_active = 1;
-
-}
-
-void turret_link()
-{
- //Net_LinkEntity(self, FALSE, 0, Turret_SendEntity);
- self.think = turret_think;
- self.nextthink = time;
-}
-
-/*
-* Standard turret initialization. use this!
-* (unless you have a very good reason not to)
-* if the return value is 0, the turret should be removed.
-*/
-float turret_stdproc_init (string cvar_base_name, float csqc_shared)
-{
- entity e,ee;
-
- if(csqc_shared)
- {
- dprint("turrets: csqc_shared requested but not implemented. expect strange things to happen.\n");
- csqc_shared = 0;
- }
-
- // Are turrets allowed atm?
- if (cvar("g_turrets") == 0)
- return 0;
-
- // Better more then once then never.
- // turret_gibs_precash();
-
- // Terrainbase spawnflag. This puts a enlongated model
- // under the turret, so it looks ok on uneaven surfaces.
- if (self.spawnflags & TSF_TERRAINBASE)
- {
- entity tb;
- //precache_model("models/turrets/terrainbase.md3");
- tb = spawn();
- setmodel(tb,"models/turrets/terrainbase.md3");
- setorigin(tb,self.origin);
- tb.solid = SOLID_BBOX;
- //makestatic(tb);
- }
-
- self.cvar_basename = cvar_base_name;
- load_unit_settings(self,self.cvar_basename,0);
-
- // Handle turret teams.
- if (cvar("g_assult") != 0)
- {
- if (!self.team)
- self.team = 14; // Assume turrets are on the defending side if not explicitly set otehrwize
- }
- else if (!teamplay)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
- else if(g_onslaught && self.targetname)
- {
- e = find(world,target,self.targetname);
- if(e != world)
- {
- self.team = e.team;
- ee = e;
- }
- }
- else if(!self.team)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
-
-
-
- /*
- * Try to guess some reasonaly defaults
- * for missing params and do sanety checks
- * thise checks could produce some "interesting" results
- * if it hits a glitch in my logic :P so try to set as mutch
- * as possible beforehand.
- */
- if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- if (!self.ticrate) self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
- else
- if (!self.ticrate) self.ticrate = 0.1; // 10 fps for normal turrets
-
- self.ticrate = bound(sys_ticrate,self.ticrate,60); // keep it sane
-
-// General stuff
- if (self.netname == "")
- self.netname = self.classname;
-
- if (!self.respawntime)
- self.respawntime = 60;
- self.respawntime = max(-1,self.respawntime);
-
- if (!self.health)
- self.health = 1000;
- self.tur_health = max(1,self.health);
-
- if (!self.turrcaps_flags)
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
-
- if (!self.damage_flags)
- self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE;
-
-// Shot stuff.
- if (!self.shot_refire)
- self.shot_refire = 1;
- self.shot_refire = bound(0.01,self.shot_refire,9999);
-
- if (!self.shot_dmg)
- self.shot_dmg = self.shot_refire * 50;
- self.shot_dmg = max(1,self.shot_dmg);
-
- if (!self.shot_radius)
- self.shot_radius = self.shot_dmg * 0.5;
- self.shot_radius = max(1,self.shot_radius);
-
- if (!self.shot_speed)
- self.shot_speed = 2500;
- self.shot_speed = max(1,self.shot_speed);
-
- if (!self.shot_spread)
- self.shot_spread = 0.0125;
- self.shot_spread = bound(0.0001,self.shot_spread,500);
-
- if (!self.shot_force)
- self.shot_force = self.shot_dmg * 0.5 + self.shot_radius * 0.5;
- self.shot_force = bound(0.001,self.shot_force,MAX_SHOT_DISTANCE * 0.5);
-
- if (!self.shot_volly)
- self.shot_volly = 1;
- self.shot_volly = bound(1,self.shot_volly,floor(self.ammo_max / self.shot_dmg));
-
- if (!self.shot_volly_refire)
- self.shot_volly_refire = self.shot_refire * self.shot_volly;
- self.shot_volly_refire = bound(self.shot_refire,self.shot_volly_refire,60);
-
- if (!self.firecheck_flags)
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
- TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK |
- TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_WORLD;
-
-// Range stuff.
- if (!self.target_range)
- self.target_range = self.shot_speed * 0.5;
- self.target_range = bound(0,self.target_range,MAX_SHOT_DISTANCE);
-
- if (!self.target_range_min)
- self.target_range_min = self.shot_radius * 2;
- self.target_range_min = bound(0,self.target_range_min,MAX_SHOT_DISTANCE);
-
- //if (!self.target_range_fire)
- // self.target_range_fire = self.target_range * 0.8;
- //self.target_range_fire = bound(0,self.target_range_fire,MAX_SHOT_DISTANCE);
-
- if (!self.target_range_optimal)
- self.target_range_optimal = self.target_range * 0.5;
- self.target_range_optimal = bound(0,self.target_range_optimal,MAX_SHOT_DISTANCE);
-
-
-// Aim stuff.
- if (!self.aim_maxrot)
- self.aim_maxrot = 90;
- self.aim_maxrot = bound(0,self.aim_maxrot,360);
-
- if (!self.aim_maxpitch)
- self.aim_maxpitch = 20;
- self.aim_maxpitch = bound(0,self.aim_maxpitch,90);
-
- if (!self.aim_speed)
- self.aim_speed = 36;
- self.aim_speed = bound(0.1,self.aim_speed, 1000);
-
- if (!self.aim_firetolerance_dist)
- self.aim_firetolerance_dist = 5 + (self.shot_radius * 2);
- self.aim_firetolerance_dist = bound(0.1,self.aim_firetolerance_dist,MAX_SHOT_DISTANCE);
-
- if (!self.aim_flags)
- {
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
- if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG)
- self.aim_flags |= TFL_AIM_GROUND2;
- }
-
- // Sill the most tested (and aim-effective)
- if (!self.track_type) self.track_type = TFL_TRACKTYPE_STEPMOTOR;
-
- if (self.track_type != TFL_TRACKTYPE_STEPMOTOR)
- {
- // Fluid / Ineria mode. Looks mutch nicer, bit experimental &
- // Can inmapt aim preformance alot.
- // needs a bit diffrent aimspeed
-
- if (!self.aim_speed)
- self.aim_speed = 180;
- self.aim_speed = bound(0.1,self.aim_speed, 1000);
-
- if (!self.track_accel_pitch)
- self.track_accel_pitch = 0.5;
-
- if (!self.track_accel_rot)
- self.track_accel_rot = 0.5;
-
- if (!self.track_blendrate)
- self.track_blendrate = 0.35;
- }
-
- if (!self.track_flags)
- self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROT;
-
-
-// Target selection stuff.
- if (!self.target_select_rangebias)
- self.target_select_rangebias = 1;
- self.target_select_rangebias = bound(-10,self.target_select_rangebias,10);
-
- if (!self.target_select_samebias)
- self.target_select_samebias = 1;
- self.target_select_samebias = bound(-10,self.target_select_samebias,10);
-
- if (!self.target_select_anglebias)
- self.target_select_anglebias = 1;
- self.target_select_anglebias = bound(-10,self.target_select_anglebias,10);
-
- if (!self.target_select_missilebias)
- self.target_select_missilebias = -10;
-
- self.target_select_missilebias = bound(-10,self.target_select_missilebias,10);
- self.target_select_playerbias = bound(-10,self.target_select_playerbias,10);
-
- if (!self.target_select_flags)
- {
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK
- | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_ANGLELIMITS;
-
- if (self.turrcaps_flags & TFL_TURRCAPS_MISSILEKILL)
- self.target_select_flags |= TFL_TARGETSELECT_MISSILES;
-
- if (self.turrcaps_flags & TFL_TURRCAPS_PLAYERKILL)
- self.target_select_flags |= TFL_TARGETSELECT_PLAYERS;
- //else
- // self.target_select_flags = TFL_TARGETSELECT_NO;
- }
-
- self.target_validate_flags = self.target_select_flags;
-
-
-// Ammo stuff
- if (!self.ammo_max)
- self.ammo_max = self.shot_dmg * 10;
- self.ammo_max = max(self.shot_dmg,self.ammo_max);
-
- if (!self.ammo)
- self.ammo = self.shot_dmg * 5;
- self.ammo = bound(0,self.ammo,self.ammo_max);
-
- if (!self.ammo_recharge)
- self.ammo_recharge = self.shot_dmg * 0.5;
- self.ammo_recharge = max(0,self.ammo_recharge);
-
- // Convert the recharge from X per sec to X per ticrate
- self.ammo_recharge = self.ammo_recharge * self.ticrate;
-
- if (!self.ammo_flags)
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
-
-// Damage stuff
- if(self.spawnflags & TSL_NO_RESPAWN)
- if not (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
- self.damage_flags |= TFL_DMG_DEATH_NORESPAWN;
-
-// Offsets & origins
- if (!self.tur_shotorg) self.tur_shotorg = '50 0 50';
-
-// End of default & sanety checks, start building the turret.
-
-// Spawn extra bits
- self.tur_head = spawn();
- self.tur_head.netname = self.tur_head.classname = "turret_head";
- self.tur_head.team = self.team;
- self.tur_head.owner = self;
-
- // Defend mode?
- 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");
- }
- }
-
-// Put pices in place
- if not (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- setorigin(self.tur_head,self.origin);
-
- // In target defend mode, aim on the spot to defend when idle.
- if(self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- {
- 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';
- }
- else
- {
- if (self.tur_defend)
- self.idle_aim = self.tur_head.angles + angleofs(self.tur_head,self.tur_defend);
- else
- self.idle_aim = self.angles;
- }
-
- if not (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- self.tur_head.angles = self.idle_aim;
-
- if (!self.health)
- self.health = 150;
-
- self.tur_health = self.health;
- self.tur_head.health = self.health;
-
- self.solid = SOLID_BBOX;
- self.tur_head.solid = SOLID_BBOX;
-
- self.takedamage = DAMAGE_AIM;
- self.tur_head.takedamage = DAMAGE_AIM;
-
- self.movetype = MOVETYPE_NOCLIP;
- self.tur_head.movetype = MOVETYPE_NOCLIP;
-
- // Team color
- if (self.team == COLOR_TEAM1) self.colormod = '1.4 0.8 0.8';
- if (self.team == COLOR_TEAM2) self.colormod = '0.8 0.8 1.4';
-
- // Attach stdprocs. override when and what needed
- if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- {
- self.turret_score_target = turret_stdproc_targetscore_support;
- self.turret_firecheckfunc = turret_stdproc_firecheck;
- self.turret_firefunc = turret_stdproc_fire;
- //self.turret_postthink = turret_stdproc_nothing;
- self.event_damage = turret_stdproc_damage;
- self.tur_head.event_damage = turret_stdproc_damage;
- }
- else
- {
- self.turret_score_target = turret_stdproc_targetscore_generic;
- self.turret_firecheckfunc = turret_stdproc_firecheck;
- self.turret_firefunc = turret_stdproc_fire;
- //self.turret_postthink = turret_stdproc_nothing;
- self.event_damage = turret_stdproc_damage;
- self.tur_head.event_damage = turret_stdproc_damage;
- //self.turret_addtarget = turret_stdproc_false;
- }
-
- self.use = turret_stdproc_use;
- self.bot_attack = TRUE;
-
- // Initiate the main AI loop
- if(csqc_shared)
- self.think = turret_link;
- else
- self.think = turret_think;
-
- self.nextthink = time + self.ticrate;
-
- self.tur_head.team = self.team;
- self.view_ofs = '0 0 0';
-
-#ifdef TURRET_DEBUG
- self.tur_dbg_start = self.nextthink;
- while (vlen(self.tur_dbg_rvec) < 2)
- self.tur_dbg_rvec = randomvec() * 4;
-
- self.tur_dbg_rvec_x = fabs(self.tur_dbg_rvec_x);
- self.tur_dbg_rvec_y = fabs(self.tur_dbg_rvec_y);
- self.tur_dbg_rvec_z = fabs(self.tur_dbg_rvec_z);
-#endif
-
- // Its all good.
- self.classname = "turret_main";
-
- self.tur_active = 1;
-
- // In ONS mode, and linked to a ONS ent. need to call the use to set team.
- if (g_onslaught && ee)
- {
- activator = ee;
- self.use();
- }
-
- return 1;
-}
-
-
+#define cvar_base "g_turrets_unit_"
+
+/*
+float turret_customizeentityforclient()
+{
+}
+
+float Turret_SendEntity(entity to, float sf)
+{
+
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
+ WriteCoord(MSG_ENTITY, self.tur_head.angles_x);
+ WriteCoord(MSG_ENTITY, self.tur_head.angles_y);
+ WriteByte(MSG_ENTITY, self.tur_head.frame);
+
+ //WriteCoord(MSG_ENTITY, self.tur_head.angles_z);
+
+ return TRUE;
+}
+*/
+
+void load_unit_settings(entity ent,string unitname,float is_reload)
+{
+ string sbase;
+
+ // dprint("Reloading turret ",e_turret.netname,"\n");
+
+ if (ent == world)
+ return;
+
+ 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';
+
+ if (ent.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ ent.tur_head.angles = '0 0 0';
+ else
+ ent.tur_head.angles = ent.angles;
+ }
+
+ 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_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
+ ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * 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_maxrot = 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_rot = cvar(strcat(sbase,"_track_accel_rot"));
+ ent.track_blendrate = cvar(strcat(sbase,"_track_blendrate"));
+
+ if(is_reload)
+ if(ent.turret_respawnhook)
+ ent.turret_respawnhook();
+
+}
+
+/*
+float turret_stdproc_true()
+{
+ return 1;
+}
+
+float turret_stdproc_false()
+{
+ return 0;
+}
+
+
+void turret_stdproc_nothing()
+{
+ return;
+}
+*/
+
+/**
+** updates enemy distances, predicted impact point/time
+** and updated aim<->predict impact distance.
+**/
+void turret_do_updates(entity t_turret)
+{
+ vector enemy_pos,oldpos;
+ entity oldself;
+
+ oldself = self;
+ self = t_turret;
+
+ enemy_pos = real_origin(self.enemy);
+
+ turret_tag_fire_update();
+
+ self.tur_shotdir_updated = normalize(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)
+ if(self.enemy)
+ {
+ oldpos = self.enemy.origin;
+ setorigin(self.enemy,self.tur_aimpos);
+ }
+
+ //dprint("NN: ", self.netname," THVN: ",self.tur_head.classname," frame:",ftos(self.tur_head.frame),"\n");
+ //dprint("self.tur_shotorg: ",vtos(self.tur_shotorg),"\n");
+ tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
+
+ if(self.firecheck_flags & TFL_FIRECHECK_VERIFIED)
+ if(self.enemy)
+ setorigin(self.enemy,oldpos);
+
+ //self.tur_impactpoint = trace_endpos;
+ self.tur_impactent = trace_ent;
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins)*0.5);
+ self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
+
+ self = oldself;
+}
+
+/*
+vector turret_fovsearch_pingpong()
+{
+ vector wish_angle;
+ if(self.phase < time)
+ {
+ if( self.tur_head.phase )
+ self.tur_head.phase = 0;
+ else
+ self.tur_head.phase = 1;
+ self.phase = time + 5;
+ }
+
+ if( self.tur_head.phase)
+ wish_angle = self.idle_aim + '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
+ else
+ wish_angle = self.idle_aim - '0 1 0' * (self.aim_maxrot * (self.target_select_fov / 360));
+
+ return wish_angle;
+}
+
+vector turret_fovsearch_steprot()
+{
+ vector wish_angle;
+ //float rot_add;
+
+ wish_angle = self.tur_head.angles;
+ wish_angle_x = self.idle_aim_x;
+
+ if (self.phase < time)
+ {
+ //rot_add = self.aim_maxrot / self.target_select_fov;
+ wish_angle_y += (self.target_select_fov * 2);
+
+ if(wish_angle_y > 360)
+ wish_angle_y = wish_angle_y - 360;
+
+ self.phase = time + 1.5;
+ }
+
+ return wish_angle;
+}
+
+vector turret_fovsearch_random()
+{
+ vector wish_angle;
+
+ if (self.phase < time)
+ {
+ wish_angle_y = random() * self.aim_maxrot;
+ if(random() < 0.5)
+ wish_angle_y *= -1;
+
+ wish_angle_x = random() * self.aim_maxpitch;
+ if(random() < 0.5)
+ wish_angle_x *= -1;
+
+ self.phase = time + 5;
+
+ self.tur_aimpos = wish_angle;
+ }
+
+ return self.idle_aim + self.tur_aimpos;
+}
+*/
+
+/**
+** Handles head rotation according to
+** the units .track_type and .track_flags
+**/
+//.entity aim_mark;
+void turret_stdproc_track()
+{
+ vector target_angle; // This is where we want to aim
+ vector move_angle; // This is where we can aim
+ float f_tmp;
+
+ if (self.track_flags == TFL_TRACK_NO)
+ return;
+
+ if(!self.tur_active)
+ target_angle = self.idle_aim - ('1 0 0' * self.aim_maxpitch);
+ else if (self.enemy == world)
+ {
+ if(time > self.lip)
+ if (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ target_angle = self.idle_aim + self.angles;
+ else
+ target_angle = self.idle_aim;
+ else
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
+ }
+ else
+ {
+ // Find the direction
+ target_angle = normalize(self.tur_aimpos - self.tur_shotorg);
+ target_angle = vectoangles(target_angle); // And make a angle
+ }
+
+ self.tur_head.angles_x = safeangle(self.tur_head.angles_x);
+ self.tur_head.angles_y = safeangle(self.tur_head.angles_y);
+
+ // Find the diffrence between where we currently aim and where we want to aim
+ vector a_off;
+
+
+ if (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ {
+ move_angle = target_angle - (self.angles + self.tur_head.angles);
+ move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
+ a_off = '0 0 0';
+
+ }
+ else
+ {
+ move_angle = target_angle - self.tur_head.angles;
+ move_angle = shortangle_vxy(move_angle,self.tur_head.angles);
+ a_off = self.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 + a_off_x > self.aim_maxpitch)
+ self.tur_head.angles_x = a_off_x + self.aim_maxpitch;
+
+ if(self.tur_head.angles_x + a_off_x < -self.aim_maxpitch)
+ self.tur_head.angles_x = a_off_x - self.aim_maxpitch;
+ }
+
+ if (self.track_flags & TFL_TRACK_ROT)
+ {
+ self.tur_head.angles_y += bound(-f_tmp, move_angle_y, f_tmp);
+ if((self.tur_head.angles_y - a_off_y) > self.aim_maxrot)
+ self.tur_head.angles_y = a_off_y + self.aim_maxrot;
+
+ if((self.tur_head.angles_y - a_off_y) < -self.aim_maxrot)
+ self.tur_head.angles_y = a_off_y - self.aim_maxrot;
+ }
+
+ 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_rot * 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) + a_off_x > self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = a_off_x + self.aim_maxpitch;
+ }
+ if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) + a_off_x < -self.aim_maxpitch)
+ {
+ self.tur_head.avelocity_x = 0;
+ self.tur_head.angles_x = a_off_x - self.aim_maxpitch;
+ }
+
+ }
+
+ // rot
+ if (self.track_flags & TFL_TRACK_ROT)
+ {
+ self.tur_head.avelocity_y = move_angle_y;
+
+ if(((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate)- a_off_y) > self.aim_maxrot)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = a_off_y + self.aim_maxrot;
+ }
+
+ if(((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) - a_off_y) < -self.aim_maxrot)
+ {
+ self.tur_head.avelocity_y = 0;
+ self.tur_head.angles_y = a_off_y - self.aim_maxrot;
+ }
+
+ }
+
+}
+
+
+/*
+ + = 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_OWM_AMMO
+ + TFL_FIRECHECK_OTHER_AMMO
+ + TFL_FIRECHECK_REFIRE
+*/
+
+/**
+** Preforms pre-fire checks based on the uints firecheck_flags
+**/
+float turret_stdproc_firecheck()
+{
+ // This one just dont care =)
+ if (self.firecheck_flags & TFL_FIRECHECK_NO) return 1;
+
+ // 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) && (self.volly_counter != self.shot_volly))
+ 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;
+
+ // Plz stop killing the world!
+ if (self.firecheck_flags & TFL_FIRECHECK_WORLD)
+ if (self.enemy == world) return 0;
+
+ // Own ammo?
+ if (self.firecheck_flags & TFL_FIRECHECK_OWM_AMMO)
+ if (self.ammo < self.shot_dmg) return 0;
+
+ // Other's ammo? (support-supply units)
+ if (self.firecheck_flags & TFL_FIRECHECK_OTHER_AMMO)
+ if (self.enemy.ammo >= self.enemy.ammo_max) return 0;
+
+ if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
+ {
+ // Not close enougth?
+ //if (self.tur_dist_aimpos > self.target_range_fire) return 0;
+
+ // To close?
+ if (self.tur_dist_aimpos < self.target_range_min) 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)
+ if (self.tur_impactent != self.enemy)
+ 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;
+}
+
+/*
+ + TFL_TARGETSELECT_NO
+ + TFL_TARGETSELECT_LOS
+ + TFL_TARGETSELECT_PLAYERS
+ + TFL_TARGETSELECT_MISSILES
+ - TFL_TARGETSELECT_TRIGGERTARGET
+ + TFL_TARGETSELECT_ANGLELIMITS
+ + TFL_TARGETSELECT_RANGELIMTS
+ + TFL_TARGETSELECT_TEAMCHECK
+ - TFL_TARGETSELECT_NOBUILTIN
+ + TFL_TARGETSELECT_OWNTEAM
+*/
+
+/**
+** Evaluate a entity for target valitity based on validate_flags
+**/
+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(checkpvs(e_target.origin, e_turret))
+ return -1;
+
+ if (!e_target)// == world)
+ 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.takedamage == DAMAGE_NO) || (e_target.health < 0))
+ return -6;
+
+ // player
+ if (e_target.flags & FL_CLIENT)
+ {
+ if not (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.turret_firefunc || 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 (validate_flags & TFL_TARGETSELECT_MISSILES)
+ return -10;
+
+ // 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_RANGELIMTS)
+ {
+ 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?
+ if(e_turret.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ {
+ tvt_thadv = angleofs3(e_turret.tur_head.origin,e_turret.angles + e_turret.tur_head.angles ,e_target);
+ //tvt_thadv = angleofs(e_turret.angles,e_target);
+ }
+ else
+ {
+ tvt_thadv = angleofs(e_turret.tur_head,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_maxrot)
+ 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.tur_shotorg,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;
+
+#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
+ float f;
+
+ m_score = 0;
+ if(self.enemy)
+ if(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;
+ }
+
+ e = findradius(self.origin,self.target_range);
+
+ // Nothing to aim at?
+ if (!e) return world;
+
+ while (e)
+ {
+ f = turret_validate_target(self,e,self.target_select_flags);
+ 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;
+}
+
+void turret_think()
+{
+ entity e;
+
+ self.nextthink = time + self.ticrate;
+
+ // ONS uses somewhat backwards linking.
+ if (teamplay)
+ {
+ if not (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_stdproc_respawn();
+ }
+
+
+ if (cvar("g_turrets_reloadcvars") == 1)
+ {
+ e = nextent(world);
+ while (e)
+ {
+ if (e.tur_head != world)
+ {
+
+ load_unit_settings(e,e.cvar_basename,1);
+ if(e.turret_postthink)
+ e.turret_postthink();
+ }
+
+ e = nextent(e);
+ }
+
+ cvar_set("g_turrets_reloadcvars","0");
+ }
+
+#ifdef TURRET_DEBUG
+ if (self.tur_dbg_tmr1 < time)
+ {
+ if (self.enemy) paint_target (self.enemy,128,self.tur_dbg_rvec,0.9);
+ paint_target(self,256,self.tur_dbg_rvec,0.9);
+ self.tur_dbg_tmr1 = time + 1;
+ }
+#endif
+
+ // Handle ammo
+ if not (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.tur_active)
+ {
+ turret_stdproc_track();
+ return;
+ }
+
+ //This is just wrong :|
+ if(self.deadflag != DEAD_NO)
+ {
+ dprint("WARNING: dead turret running the think function!\n");
+ 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 (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.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_stdproc_aim_generic();
+
+ // Turn & pitch?
+ if (!self.track_flags & TFL_TRACK_NO)
+ turret_stdproc_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.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_stdproc_aim_generic();
+
+ // Turn & pitch
+ if (!self.track_flags & TFL_TRACK_NO)
+ turret_stdproc_track();
+
+ turret_do_updates(self);
+
+ // Fire!
+ if (self.turret_firecheckfunc() != 0)
+ turret_fire();
+
+ if(self.turret_postthink)
+ self.turret_postthink();
+
+ return;
+ }
+
+ // Check if we have a vailid enemy, and try to find one if we dont.
+ if( ((self.target_select_time + cvar("g_turrets_targetscan_maxdelay")) < time)
+ || (turret_validate_target(self,self.enemy,self.target_validate_flags) <= 0) )
+ if not (self.target_select_time + cvar("g_turrets_targetscan_mindelay") > time)
+ {
+ self.enemy = turret_select_target();
+ //if(self.enemy)
+ self.target_select_time = time;
+
+ }
+
+
+ // No target, just go to idle, do any custom stuff and bail.
+ if (self.enemy == world)
+ {
+ // Turn & pitch
+ if (!self.track_flags & TFL_TRACK_NO)
+ turret_stdproc_track();
+
+ // do any per-turret stuff
+ if(self.turret_postthink)
+ self.turret_postthink();
+
+ // And bail.
+ return;
+ }
+ else
+ self.lip = time + cvar("g_turrets_aimidle_delay"); // Keep track of the last time we had a target.
+
+ // Predict?
+ if not((self.aim_flags & TFL_AIM_NO))
+ self.tur_aimpos = turret_stdproc_aim_generic();
+
+ // Turn & pitch?
+ if (!self.track_flags & TFL_TRACK_NO)
+ turret_stdproc_track();
+
+ turret_do_updates(self);
+ // Fire?
+ if (self.turret_firecheckfunc())
+ turret_fire();
+ }
+
+ // do any per-turret stuff
+ if(self.turret_postthink)
+ self.turret_postthink();
+}
+
+void turret_fire()
+{
+ if (cvar("g_turrets_nofire") != 0)
+ return;
+
+ if ((!self.tur_active) || (self.deadflag != DEAD_NO))
+ return;
+
+ self.turret_firefunc();
+
+ self.attack_finished_single = time + self.shot_refire;
+ self.ammo = 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_dbg_rvec, self.tur_impacttime + 0.25);
+#endif
+}
+
+void turret_stdproc_fire()
+{
+ dprint("^1Bang, ^3your dead^7 ",self.enemy.netname,"! ^1(turret with no real firefunc)\n");
+}
+
+/*
+ When .used a turret switch team to activator.team.
+ If activator is world, the turrets goes inactive.
+*/
+void turret_stdproc_use()
+{
+ dprint("Turret ",self.netname, " used by ",activator.classname,"\n");
+
+ self.team = activator.team;
+
+ if(self.team == 0)
+ self.tur_active = 0;
+ else
+ self.tur_active = 1;
+
+}
+
+void turret_link()
+{
+ //Net_LinkEntity(self, FALSE, 0, Turret_SendEntity);
+ self.think = turret_think;
+ self.nextthink = time;
+}
+
+/*
+* Standard turret initialization. use this!
+* (unless you have a very good reason not to)
+* if the return value is 0, the turret should be removed.
+*/
+float turret_stdproc_init (string cvar_base_name, float csqc_shared)
+{
+ entity e,ee;
+
+ if(csqc_shared)
+ {
+ dprint("turrets: csqc_shared requested but not implemented. expect strange things to happen.\n");
+ csqc_shared = 0;
+ }
+
+ // Are turrets allowed atm?
+ if (cvar("g_turrets") == 0)
+ return 0;
+
+ // Better more then once then never.
+ // turret_gibs_precash();
+
+ // Terrainbase spawnflag. This puts a enlongated model
+ // under the turret, so it looks ok on uneaven surfaces.
+ if (self.spawnflags & TSF_TERRAINBASE)
+ {
+ entity tb;
+ //precache_model("models/turrets/terrainbase.md3");
+ tb = spawn();
+ setmodel(tb,"models/turrets/terrainbase.md3");
+ setorigin(tb,self.origin);
+ tb.solid = SOLID_BBOX;
+ //makestatic(tb);
+ }
+
+ self.cvar_basename = cvar_base_name;
+ load_unit_settings(self,self.cvar_basename,0);
+
+ // Handle turret teams.
+ if (cvar("g_assult") != 0)
+ {
+ if (!self.team)
+ self.team = 14; // Assume turrets are on the defending side if not explicitly set otehrwize
+ }
+ else if (!teamplay)
+ self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
+ else if(g_onslaught && self.targetname)
+ {
+ e = find(world,target,self.targetname);
+ if(e != world)
+ {
+ self.team = e.team;
+ ee = e;
+ }
+ }
+ else if(!self.team)
+ self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
+
+
+
+ /*
+ * Try to guess some reasonaly defaults
+ * for missing params and do sanety checks
+ * thise checks could produce some "interesting" results
+ * if it hits a glitch in my logic :P so try to set as mutch
+ * as possible beforehand.
+ */
+ if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
+ if (!self.ticrate) self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
+ else
+ if (!self.ticrate) self.ticrate = 0.1; // 10 fps for normal turrets
+
+ self.ticrate = bound(sys_ticrate,self.ticrate,60); // keep it sane
+
+// General stuff
+ if (self.netname == "")
+ self.netname = self.classname;
+
+ if (!self.respawntime)
+ self.respawntime = 60;
+ self.respawntime = max(-1,self.respawntime);
+
+ if (!self.health)
+ self.health = 1000;
+ self.tur_health = max(1,self.health);
+
+ if (!self.turrcaps_flags)
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
+
+ if (!self.damage_flags)
+ self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE;
+
+// Shot stuff.
+ if (!self.shot_refire)
+ self.shot_refire = 1;
+ self.shot_refire = bound(0.01,self.shot_refire,9999);
+
+ if (!self.shot_dmg)
+ self.shot_dmg = self.shot_refire * 50;
+ self.shot_dmg = max(1,self.shot_dmg);
+
+ if (!self.shot_radius)
+ self.shot_radius = self.shot_dmg * 0.5;
+ self.shot_radius = max(1,self.shot_radius);
+
+ if (!self.shot_speed)
+ self.shot_speed = 2500;
+ self.shot_speed = max(1,self.shot_speed);
+
+ if (!self.shot_spread)
+ self.shot_spread = 0.0125;
+ self.shot_spread = bound(0.0001,self.shot_spread,500);
+
+ if (!self.shot_force)
+ self.shot_force = self.shot_dmg * 0.5 + self.shot_radius * 0.5;
+ self.shot_force = bound(0.001,self.shot_force,MAX_SHOT_DISTANCE * 0.5);
+
+ if (!self.shot_volly)
+ self.shot_volly = 1;
+ self.shot_volly = bound(1,self.shot_volly,floor(self.ammo_max / self.shot_dmg));
+
+ if (!self.shot_volly_refire)
+ self.shot_volly_refire = self.shot_refire * self.shot_volly;
+ self.shot_volly_refire = bound(self.shot_refire,self.shot_volly_refire,60);
+
+ if (!self.firecheck_flags)
+ self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
+ TFL_FIRECHECK_LOS | TFL_FIRECHECK_AIMDIST | TFL_FIRECHECK_TEAMCECK |
+ TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_WORLD;
+
+// Range stuff.
+ if (!self.target_range)
+ self.target_range = self.shot_speed * 0.5;
+ self.target_range = bound(0,self.target_range,MAX_SHOT_DISTANCE);
+
+ if (!self.target_range_min)
+ self.target_range_min = self.shot_radius * 2;
+ self.target_range_min = bound(0,self.target_range_min,MAX_SHOT_DISTANCE);
+
+ //if (!self.target_range_fire)
+ // self.target_range_fire = self.target_range * 0.8;
+ //self.target_range_fire = bound(0,self.target_range_fire,MAX_SHOT_DISTANCE);
+
+ if (!self.target_range_optimal)
+ self.target_range_optimal = self.target_range * 0.5;
+ self.target_range_optimal = bound(0,self.target_range_optimal,MAX_SHOT_DISTANCE);
+
+
+// Aim stuff.
+ if (!self.aim_maxrot)
+ self.aim_maxrot = 90;
+ self.aim_maxrot = bound(0,self.aim_maxrot,360);
+
+ if (!self.aim_maxpitch)
+ self.aim_maxpitch = 20;
+ self.aim_maxpitch = bound(0,self.aim_maxpitch,90);
+
+ if (!self.aim_speed)
+ self.aim_speed = 36;
+ self.aim_speed = bound(0.1,self.aim_speed, 1000);
+
+ if (!self.aim_firetolerance_dist)
+ self.aim_firetolerance_dist = 5 + (self.shot_radius * 2);
+ self.aim_firetolerance_dist = bound(0.1,self.aim_firetolerance_dist,MAX_SHOT_DISTANCE);
+
+ if (!self.aim_flags)
+ {
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+ if(self.turrcaps_flags & TFL_TURRCAPS_RADIUSDMG)
+ self.aim_flags |= TFL_AIM_GROUND2;
+ }
+
+ // Sill the most tested (and aim-effective)
+ if (!self.track_type) self.track_type = TFL_TRACKTYPE_STEPMOTOR;
+
+ if (self.track_type != TFL_TRACKTYPE_STEPMOTOR)
+ {
+ // Fluid / Ineria mode. Looks mutch nicer, bit experimental &
+ // Can inmapt aim preformance alot.
+ // needs a bit diffrent aimspeed
+
+ if (!self.aim_speed)
+ self.aim_speed = 180;
+ self.aim_speed = bound(0.1,self.aim_speed, 1000);
+
+ if (!self.track_accel_pitch)
+ self.track_accel_pitch = 0.5;
+
+ if (!self.track_accel_rot)
+ self.track_accel_rot = 0.5;
+
+ if (!self.track_blendrate)
+ self.track_blendrate = 0.35;
+ }
+
+ if (!self.track_flags)
+ self.track_flags = TFL_TRACK_PITCH | TFL_TRACK_ROT;
+
+
+// Target selection stuff.
+ if (!self.target_select_rangebias)
+ self.target_select_rangebias = 1;
+ self.target_select_rangebias = bound(-10,self.target_select_rangebias,10);
+
+ if (!self.target_select_samebias)
+ self.target_select_samebias = 1;
+ self.target_select_samebias = bound(-10,self.target_select_samebias,10);
+
+ if (!self.target_select_anglebias)
+ self.target_select_anglebias = 1;
+ self.target_select_anglebias = bound(-10,self.target_select_anglebias,10);
+
+ if (!self.target_select_missilebias)
+ self.target_select_missilebias = -10;
+
+ self.target_select_missilebias = bound(-10,self.target_select_missilebias,10);
+ self.target_select_playerbias = bound(-10,self.target_select_playerbias,10);
+
+ if (!self.target_select_flags)
+ {
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_TEAMCHECK
+ | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_ANGLELIMITS;
+
+ if (self.turrcaps_flags & TFL_TURRCAPS_MISSILEKILL)
+ self.target_select_flags |= TFL_TARGETSELECT_MISSILES;
+
+ if (self.turrcaps_flags & TFL_TURRCAPS_PLAYERKILL)
+ self.target_select_flags |= TFL_TARGETSELECT_PLAYERS;
+ //else
+ // self.target_select_flags = TFL_TARGETSELECT_NO;
+ }
+
+ self.target_validate_flags = self.target_select_flags;
+
+
+// Ammo stuff
+ if (!self.ammo_max)
+ self.ammo_max = self.shot_dmg * 10;
+ self.ammo_max = max(self.shot_dmg,self.ammo_max);
+
+ if (!self.ammo)
+ self.ammo = self.shot_dmg * 5;
+ self.ammo = bound(0,self.ammo,self.ammo_max);
+
+ if (!self.ammo_recharge)
+ self.ammo_recharge = self.shot_dmg * 0.5;
+ self.ammo_recharge = max(0,self.ammo_recharge);
+
+ // Convert the recharge from X per sec to X per ticrate
+ self.ammo_recharge = self.ammo_recharge * self.ticrate;
+
+ if (!self.ammo_flags)
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+
+// Damage stuff
+ if(self.spawnflags & TSL_NO_RESPAWN)
+ if not (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
+ self.damage_flags |= TFL_DMG_DEATH_NORESPAWN;
+
+// Offsets & origins
+ if (!self.tur_shotorg) self.tur_shotorg = '50 0 50';
+
+// End of default & sanety checks, start building the turret.
+
+// Spawn extra bits
+ self.tur_head = spawn();
+ self.tur_head.netname = self.tur_head.classname = "turret_head";
+ self.tur_head.team = self.team;
+ self.tur_head.owner = self;
+
+ // Defend mode?
+ 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");
+ }
+ }
+
+// Put pices in place
+ if not (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ setorigin(self.tur_head,self.origin);
+
+ // In target defend mode, aim on the spot to defend when idle.
+ if(self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ {
+ 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';
+ }
+ else
+ {
+ if (self.tur_defend)
+ self.idle_aim = self.tur_head.angles + angleofs(self.tur_head,self.tur_defend);
+ else
+ self.idle_aim = self.angles;
+ }
+
+ if not (self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
+ self.tur_head.angles = self.idle_aim;
+
+ if (!self.health)
+ self.health = 150;
+
+ self.tur_health = self.health;
+ self.tur_head.health = self.health;
+
+ self.solid = SOLID_BBOX;
+ self.tur_head.solid = SOLID_BBOX;
+
+ self.takedamage = DAMAGE_AIM;
+ self.tur_head.takedamage = DAMAGE_AIM;
+
+ self.movetype = MOVETYPE_NOCLIP;
+ self.tur_head.movetype = MOVETYPE_NOCLIP;
+
+ // Team color
+ if (self.team == COLOR_TEAM1) self.colormod = '1.4 0.8 0.8';
+ if (self.team == COLOR_TEAM2) self.colormod = '0.8 0.8 1.4';
+
+ // Attach stdprocs. override when and what needed
+ if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
+ {
+ self.turret_score_target = turret_stdproc_targetscore_support;
+ self.turret_firecheckfunc = turret_stdproc_firecheck;
+ self.turret_firefunc = turret_stdproc_fire;
+ //self.turret_postthink = turret_stdproc_nothing;
+ self.event_damage = turret_stdproc_damage;
+ self.tur_head.event_damage = turret_stdproc_damage;
+ }
+ else
+ {
+ self.turret_score_target = turret_stdproc_targetscore_generic;
+ self.turret_firecheckfunc = turret_stdproc_firecheck;
+ self.turret_firefunc = turret_stdproc_fire;
+ //self.turret_postthink = turret_stdproc_nothing;
+ self.event_damage = turret_stdproc_damage;
+ self.tur_head.event_damage = turret_stdproc_damage;
+ //self.turret_addtarget = turret_stdproc_false;
+ }
+
+ self.use = turret_stdproc_use;
+ self.bot_attack = TRUE;
+
+ // Initiate the main AI loop
+ if(csqc_shared)
+ self.think = turret_link;
+ else
+ self.think = turret_think;
+
+ self.nextthink = time + self.ticrate;
+
+ self.tur_head.team = self.team;
+ self.view_ofs = '0 0 0';
+
+#ifdef TURRET_DEBUG
+ self.tur_dbg_start = self.nextthink;
+ while (vlen(self.tur_dbg_rvec) < 2)
+ self.tur_dbg_rvec = randomvec() * 4;
+
+ self.tur_dbg_rvec_x = fabs(self.tur_dbg_rvec_x);
+ self.tur_dbg_rvec_y = fabs(self.tur_dbg_rvec_y);
+ self.tur_dbg_rvec_z = fabs(self.tur_dbg_rvec_z);
+#endif
+
+ // Its all good.
+ self.classname = "turret_main";
+
+ self.tur_active = 1;
+
+ // In ONS mode, and linked to a ONS ent. need to call the use to set team.
+ if (g_onslaught && ee)
+ {
+ activator = ee;
+ self.use();
+ }
+
+ return 1;
+}
+
+
Property changes on: trunk/data/qcsrc/server/tturrets/system/system_main.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/system/system_misc.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/system/system_misc.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/system/system_misc.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,406 +1,406 @@
-//--// Some support routines //--//
-
-#define anglemodss(a) (a - floor(a / 360) * 360)
-float(float v) anglemods =
-{
- v = v - 360 * floor(v / 360);
- return v;
-};
-float safeangle(float a)
-{
- if((a > -361) && (a < 361))
- return a;
-
- a -= (360 * floor(a / 360));
-
- return a;
-}
-
-float shortangle_f(float ang1,float ang2)
-{
- if(ang1 > ang2)
- {
- if(ang1 > 180)
- return ang1 - 360;
- }
- else
- {
- if(ang1 < -180)
- return ang1 + 360;
- }
-
- return ang1;
-}
-
-vector shortangle_v(vector ang1,vector ang2)
-{
- vector vtmp;
-
- vtmp_x = shortangle_f(ang1_x,ang2_x);
- vtmp_y = shortangle_f(ang1_y,ang2_y);
- vtmp_z = shortangle_f(ang1_z,ang2_z);
-
- return vtmp;
-}
-
-vector shortangle_vxy(vector ang1,vector ang2)
-{
- vector vtmp;
-
- vtmp_x = shortangle_f(ang1_x,ang2_x);
- vtmp_y = shortangle_f(ang1_y,ang2_y);
-
- return vtmp;
-}
-
-// Get real origin
-vector real_origin(entity ent)
-{
- entity e;
- vector v;
-
- e = ent.tag_entity;
- while(e)
- {
- // v = v + e.origin;
- v = v + ((e.absmin + e.absmax) * 0.5);
- e = e.tag_entity;
- }
- //v = v + ent.origin;
- v = v + ((ent.absmin + ent.absmax) * 0.5);
- return v;
-}
-
-// Plug this into wherever precache is done.
-void g_turrets_common_precash()
-{
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/marker.md3");
-}
-
-void SUB_Remove();
-void marker_think()
-{
- if(self.cnt)
- if(self.cnt < time)
- {
- self.think = SUB_Remove;
- self.nextthink = time;
- return;
- }
-
- self.frame += 1;
- if(self.frame > 29)
- self.frame = 0;
-
- self.nextthink = time;
-}
-
-void mark_error(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "error_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 0;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-void mark_info(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "info_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 1;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-entity mark_misc(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "mark_misc";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 3;
- if(lifetime)
- err.cnt = lifetime + time;
- return err;
-}
-
-/*
-* Paint a v_color colord circle on target onwho
-* that fades away over f_time
-*/
-void paint_target(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- //setsize(e, '0 0 0', '0 0 0');
- //setattachment(e,onwho,"");
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
-
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
- e.avelocity_x = -128;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target3(vector where, float f_size, vector v_color, float f_time)
-{
- entity e;
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
- setorigin(e,where+ '0 0 1');
- e.movetype = MOVETYPE_NONE;
- e.velocity = '0 0 0';
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-/*
-* Return the angle between two enteties
-*/
-vector angleofs(entity from, entity to)
-{
- vector v_res;
-
- // makevectors(from.angles);
- v_res = normalize(to.origin - from.origin);
- v_res = vectoangles(v_res);
- v_res = v_res - from.angles;
-
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
-
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
-
- return v_res;
-}
-
-vector angleofs2(entity from, vector to)
-{
- vector v_res;
-
- // makevectors(from.angles);
- v_res = normalize(to - from.origin);
- v_res = vectoangles(v_res);
- v_res = v_res - from.angles;
-
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
-
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
-
- return v_res;
-}
-
-vector angleofs3(vector from,vector from_a, entity to)
-{
- vector v_res;
-
- // makevectors(from.angles);
- v_res = normalize(to.origin - from);
- v_res = vectoangles(v_res);
- v_res = v_res - from_a;
-
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
-
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
-
- return v_res;
-}
-
-float turret_tag_setup()
-{
- if(!self.tur_head)
- {
- dprint("Call to turret_tag_setup with self.tur_head missing!\n");
- self.tur_shotorg = '0 0 0';
- return 0;
- }
-
- setorigin(self.tur_head,gettaginfo(self,gettagindex(self,"tag_head")));
- self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
-
- v_forward = normalize(v_forward);
-
- return 1;
-}
-
-float turret_tag_fire_update()
-{
- if(!self.tur_head)
- {
- dprint("Call to turret_tag_fire_update with self.tur_head missing!\n");
- self.tur_shotorg = '0 0 0';
- return 0;
- }
-
- self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
- v_forward = normalize(v_forward);
-
- //dprint("update: tur_shotorg: ",vtos(self.tur_shotorg)," origin:", vtos(self.tur_head.origin), " angels: ", vtos(self.tur_head.angles),"\n");
-
- return 1;
-}
-
-void FireImoBeam (vector start,vector end,vector smin,vector smax,
- float bforce,float f_dmg,float f_velfactor, float deathtype)
-
-{
- local vector hitloc, force, endpoint, dir;
- local entity ent;
-
- dir = normalize(end - start);
- force = dir * bforce;
-
- // go a little bit into the wall because we need to hit this wall later
- end = end + dir;
-
- // trace multiple times until we hit a wall, each obstacle will be made unsolid.
- // note down which entities were hit so we can damage them later
- while (1)
- {
- tracebox(start, smin, smax, end, FALSE, self);
-
- // if it is world we can't hurt it so stop now
- if (trace_ent == world || trace_fraction == 1)
- break;
-
- if (trace_ent.solid == SOLID_BSP)
- break;
-
- // make the entity non-solid so we can hit the next one
- trace_ent.railgunhit = TRUE;
- trace_ent.railgunhitloc = end;
- trace_ent.railgunhitsolidbackup = trace_ent.solid;
-
- // stop if this is a wall
-
- // make the entity non-solid
- trace_ent.solid = SOLID_NOT;
- }
-
- endpoint = trace_endpos;
-
- // find all the entities the railgun hit and restore their solid state
- ent = findfloat(world, railgunhit, TRUE);
- while (ent)
- {
- // restore their solid type
- ent.solid = ent.railgunhitsolidbackup;
- ent = findfloat(ent, railgunhit, TRUE);
- }
-
- // find all the entities the railgun hit and hurt them
- ent = findfloat(world, railgunhit, TRUE);
- while (ent)
- {
- // get the details we need to call the damage function
- hitloc = ent.railgunhitloc;
- ent.railgunhitloc = '0 0 0';
- ent.railgunhitsolidbackup = SOLID_NOT;
- ent.railgunhit = FALSE;
-
- // apply the damage
- if (ent.takedamage)
- {
- Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
- ent.velocity = ent.velocity * f_velfactor;
- //ent.alpha = 0.25 + random() * 0.75;
- }
-
- // advance to the next entity
- ent = findfloat(ent, railgunhit, TRUE);
- }
- trace_endpos = endpoint;
-}
-
-void turrets_precash()
-{
- precache_model ("models/turrets/base-gib1.md3");
- precache_model ("models/turrets/base-gib2.md3");
- precache_model ("models/turrets/base-gib3.md3");
- precache_model ("models/turrets/base-gib4.md3");
-
- precache_model ("models/turrets/head-gib1.md3");
- precache_model ("models/turrets/head-gib2.md3");
- precache_model ("models/turrets/head-gib3.md3");
- precache_model ("models/turrets/head-gib4.md3");
- precache_model ("models/turrets/terrainbase.md3");
-
- //precache_model ("models/turrets/base.md3");
- //precache_model ("models/turrets/flac.md3");
- //precache_model ("models/turrets/pd_proj.md3");
- //precache_model ("models/turrets/reactor.md3");
- //precache_model ("models/turrets/mlrs_rocket.md3");
- //precache_model ("models/turrets/hellion.md3");
- //precache_model ("models/turrets/hunter2.md3");
- //precache_model ("models/turrets/hk.md3");
- //precache_model ("models/turrets/machinegun.md3");
- //precache_model ("models/turrets/rocket.md3");
- //precache_model ("models/turrets/mlrs.md3");
- //precache_model ("models/turrets/phaser.md3");
- //precache_model ("models/turrets/phaser_beam.md3");
- //precache_model ("models/turrets/plasmad.md3");
- //precache_model ("models/turrets/plasma.md3");
- //precache_model ("models/turrets/tesla_head.md3");
- //precache_model ("models/turrets/tesla_base.md3");
-
-#if 0
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/pathlib/goodsquare.md3");
- precache_model ("models/pathlib/badsquare.md3");
- precache_model ("models/pathlib/square.md3");
- precache_model ("models/pathlib/edge.md3");
-#endif
-}
+//--// Some support routines //--//
+
+#define anglemodss(a) (a - floor(a / 360) * 360)
+float(float v) anglemods =
+{
+ v = v - 360 * floor(v / 360);
+ return v;
+};
+float safeangle(float a)
+{
+ if((a > -361) && (a < 361))
+ return a;
+
+ a -= (360 * floor(a / 360));
+
+ return a;
+}
+
+float shortangle_f(float ang1,float ang2)
+{
+ if(ang1 > ang2)
+ {
+ if(ang1 > 180)
+ return ang1 - 360;
+ }
+ else
+ {
+ if(ang1 < -180)
+ return ang1 + 360;
+ }
+
+ return ang1;
+}
+
+vector shortangle_v(vector ang1,vector ang2)
+{
+ vector vtmp;
+
+ vtmp_x = shortangle_f(ang1_x,ang2_x);
+ vtmp_y = shortangle_f(ang1_y,ang2_y);
+ vtmp_z = shortangle_f(ang1_z,ang2_z);
+
+ return vtmp;
+}
+
+vector shortangle_vxy(vector ang1,vector ang2)
+{
+ vector vtmp;
+
+ vtmp_x = shortangle_f(ang1_x,ang2_x);
+ vtmp_y = shortangle_f(ang1_y,ang2_y);
+
+ return vtmp;
+}
+
+// Get real origin
+vector real_origin(entity ent)
+{
+ entity e;
+ vector v;
+
+ e = ent.tag_entity;
+ while(e)
+ {
+ // v = v + e.origin;
+ v = v + ((e.absmin + e.absmax) * 0.5);
+ e = e.tag_entity;
+ }
+ //v = v + ent.origin;
+ v = v + ((ent.absmin + ent.absmax) * 0.5);
+ return v;
+}
+
+// Plug this into wherever precache is done.
+void g_turrets_common_precash()
+{
+ precache_model ("models/turrets/c512.md3");
+ precache_model ("models/marker.md3");
+}
+
+void SUB_Remove();
+void marker_think()
+{
+ if(self.cnt)
+ if(self.cnt < time)
+ {
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ return;
+ }
+
+ self.frame += 1;
+ if(self.frame > 29)
+ self.frame = 0;
+
+ self.nextthink = time;
+}
+
+void mark_error(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "error_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 0;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+void mark_info(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "info_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 1;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+entity mark_misc(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "mark_misc";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 3;
+ if(lifetime)
+ err.cnt = lifetime + time;
+ return err;
+}
+
+/*
+* Paint a v_color colord circle on target onwho
+* that fades away over f_time
+*/
+void paint_target(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ //setsize(e, '0 0 0', '0 0 0');
+ //setattachment(e,onwho,"");
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+ e.avelocity_x = -128;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target3(vector where, float f_size, vector v_color, float f_time)
+{
+ entity e;
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+ setorigin(e,where+ '0 0 1');
+ e.movetype = MOVETYPE_NONE;
+ e.velocity = '0 0 0';
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+/*
+* Return the angle between two enteties
+*/
+vector angleofs(entity from, entity to)
+{
+ vector v_res;
+
+ // makevectors(from.angles);
+ v_res = normalize(to.origin - from.origin);
+ v_res = vectoangles(v_res);
+ v_res = v_res - from.angles;
+
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
+
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
+
+ return v_res;
+}
+
+vector angleofs2(entity from, vector to)
+{
+ vector v_res;
+
+ // makevectors(from.angles);
+ v_res = normalize(to - from.origin);
+ v_res = vectoangles(v_res);
+ v_res = v_res - from.angles;
+
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
+
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
+
+ return v_res;
+}
+
+vector angleofs3(vector from,vector from_a, entity to)
+{
+ vector v_res;
+
+ // makevectors(from.angles);
+ v_res = normalize(to.origin - from);
+ v_res = vectoangles(v_res);
+ v_res = v_res - from_a;
+
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
+
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
+
+ return v_res;
+}
+
+float turret_tag_setup()
+{
+ if(!self.tur_head)
+ {
+ dprint("Call to turret_tag_setup with self.tur_head missing!\n");
+ self.tur_shotorg = '0 0 0';
+ return 0;
+ }
+
+ setorigin(self.tur_head,gettaginfo(self,gettagindex(self,"tag_head")));
+ self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
+
+ v_forward = normalize(v_forward);
+
+ return 1;
+}
+
+float turret_tag_fire_update()
+{
+ if(!self.tur_head)
+ {
+ dprint("Call to turret_tag_fire_update with self.tur_head missing!\n");
+ self.tur_shotorg = '0 0 0';
+ return 0;
+ }
+
+ self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
+ v_forward = normalize(v_forward);
+
+ //dprint("update: tur_shotorg: ",vtos(self.tur_shotorg)," origin:", vtos(self.tur_head.origin), " angels: ", vtos(self.tur_head.angles),"\n");
+
+ return 1;
+}
+
+void FireImoBeam (vector start,vector end,vector smin,vector smax,
+ float bforce,float f_dmg,float f_velfactor, float deathtype)
+
+{
+ local vector hitloc, force, endpoint, dir;
+ local entity ent;
+
+ dir = normalize(end - start);
+ force = dir * bforce;
+
+ // go a little bit into the wall because we need to hit this wall later
+ end = end + dir;
+
+ // trace multiple times until we hit a wall, each obstacle will be made unsolid.
+ // note down which entities were hit so we can damage them later
+ while (1)
+ {
+ tracebox(start, smin, smax, end, FALSE, self);
+
+ // if it is world we can't hurt it so stop now
+ if (trace_ent == world || trace_fraction == 1)
+ break;
+
+ if (trace_ent.solid == SOLID_BSP)
+ break;
+
+ // make the entity non-solid so we can hit the next one
+ trace_ent.railgunhit = TRUE;
+ trace_ent.railgunhitloc = end;
+ trace_ent.railgunhitsolidbackup = trace_ent.solid;
+
+ // stop if this is a wall
+
+ // make the entity non-solid
+ trace_ent.solid = SOLID_NOT;
+ }
+
+ endpoint = trace_endpos;
+
+ // find all the entities the railgun hit and restore their solid state
+ ent = findfloat(world, railgunhit, TRUE);
+ while (ent)
+ {
+ // restore their solid type
+ ent.solid = ent.railgunhitsolidbackup;
+ ent = findfloat(ent, railgunhit, TRUE);
+ }
+
+ // find all the entities the railgun hit and hurt them
+ ent = findfloat(world, railgunhit, TRUE);
+ while (ent)
+ {
+ // get the details we need to call the damage function
+ hitloc = ent.railgunhitloc;
+ ent.railgunhitloc = '0 0 0';
+ ent.railgunhitsolidbackup = SOLID_NOT;
+ ent.railgunhit = FALSE;
+
+ // apply the damage
+ if (ent.takedamage)
+ {
+ Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
+ ent.velocity = ent.velocity * f_velfactor;
+ //ent.alpha = 0.25 + random() * 0.75;
+ }
+
+ // advance to the next entity
+ ent = findfloat(ent, railgunhit, TRUE);
+ }
+ trace_endpos = endpoint;
+}
+
+void turrets_precash()
+{
+ precache_model ("models/turrets/base-gib1.md3");
+ precache_model ("models/turrets/base-gib2.md3");
+ precache_model ("models/turrets/base-gib3.md3");
+ precache_model ("models/turrets/base-gib4.md3");
+
+ precache_model ("models/turrets/head-gib1.md3");
+ precache_model ("models/turrets/head-gib2.md3");
+ precache_model ("models/turrets/head-gib3.md3");
+ precache_model ("models/turrets/head-gib4.md3");
+ precache_model ("models/turrets/terrainbase.md3");
+
+ //precache_model ("models/turrets/base.md3");
+ //precache_model ("models/turrets/flac.md3");
+ //precache_model ("models/turrets/pd_proj.md3");
+ //precache_model ("models/turrets/reactor.md3");
+ //precache_model ("models/turrets/mlrs_rocket.md3");
+ //precache_model ("models/turrets/hellion.md3");
+ //precache_model ("models/turrets/hunter2.md3");
+ //precache_model ("models/turrets/hk.md3");
+ //precache_model ("models/turrets/machinegun.md3");
+ //precache_model ("models/turrets/rocket.md3");
+ //precache_model ("models/turrets/mlrs.md3");
+ //precache_model ("models/turrets/phaser.md3");
+ //precache_model ("models/turrets/phaser_beam.md3");
+ //precache_model ("models/turrets/plasmad.md3");
+ //precache_model ("models/turrets/plasma.md3");
+ //precache_model ("models/turrets/tesla_head.md3");
+ //precache_model ("models/turrets/tesla_base.md3");
+
+#if 0
+ precache_model ("models/turrets/c512.md3");
+ precache_model ("models/pathlib/goodsquare.md3");
+ precache_model ("models/pathlib/badsquare.md3");
+ precache_model ("models/pathlib/square.md3");
+ precache_model ("models/pathlib/edge.md3");
+#endif
+}
Property changes on: trunk/data/qcsrc/server/tturrets/system/system_misc.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,166 +1,166 @@
-/*
-.float target_select_flags; /// target selection flags
-float TFL_TARGETSELECT_NO = 1; /// Dont select a target on its own.
-float TFL_TARGETSELECT_LOS = 2; /// Need line of sight
-float TFL_TARGETSELECT_PLAYERS = 4; /// Players are valid targets
-float TFL_TARGETSELECT_MISSILES = 8; /// Missiles are valid targets
-float TFL_TARGETSELECT_TRIGGERTARGET = 16; /// Responds to turret_trigger_target events
-float TFL_TARGETSELECT_ANGLELIMITS = 32; /// Angular limitations of turret head limits target selection
-float TFL_TARGETSELECT_RANGELIMTS = 64; /// Range limits apply in targetselection
-float TFL_TARGETSELECT_TEAMCHECK = 128; /// Consider team own <-> targets team
-float TFL_TARGETSELECT_NOBUILTIN = 256; /// Cant select targets on its own. needs to be triggerd or slaved.
-float TFL_TARGETSELECT_OWNTEAM = 512;
-*/
-
-float turret_stdproc_targetscore_support(entity e_turret,entity e_target)
-{
- float score; // Total score
- float s_score,d_score;
-
- if (e_turret.enemy == e_target) s_score = 1;
-
- d_score = min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist);
-
- score = (d_score * e_turret.target_select_rangebias) +
- (s_score * e_turret.target_select_samebias);
-
- return score;
-}
-
-/*
-* Generic bias aware score system.
-*/
-float turret_stdproc_targetscore_generic(entity e_turret,entity e_target)
-{
- //vector v_tmp;
- float d_dist; // Defendmode Distance
-
- float score; // Total score
-
- float d_score; // Distance score
- float a_score; // Angular score
- float m_score; // missile score
- float p_score; // player score
- //float da_score; // Distance from aimpoint score
-
- float ikr; // ideal kill range
-
- if(!e_target) return 0;
-
- //if (e_target == e_turret.enemy) s_score = 1;
-
- if (e_turret.tur_defend)
- {
- d_dist = vlen(real_origin(e_target) - e_turret.tur_defend.origin);
- ikr = vlen(e_turret.origin - e_turret.tur_defend.origin);
- d_score = 1 - d_dist / e_turret.target_range;
- }
- else
- {
- // Make a normlized value base on the targets distance from our optimal killzone
- ikr = e_turret.target_range_optimal;
- d_score = min(ikr,tvt_dist) / max(ikr,tvt_dist);
- }
-
- /*
- // Determine the maximum time it could take this turrent to aim at someting.
- max_aim_delay = (max(e_turret.aim_maxrot,e_turret.aim_maxpitch) / e_turret.aim_speed * 2);
-
- // Find out how long it would take to aim at this taget.
- aim_delay = (thadf+0.01) / e_turret.aim_speed;
-
- // Turn this info into a normalized value.
- aim_delay = (min(max_aim_delay,aim_delay) / max_aim_delay);
- a_score = 1 - aim_delay;
- */
-
- //a_score = 1 - (tvt_thadf / max(e_turret.aim_maxrot,e_turret.aim_maxpitch));
- a_score = 1 - tvt_thadf / e_turret.aim_maxrot;
-
- if ((e_turret.target_select_missilebias > 0) && (e_target.flags & FL_PROJECTILE))
- m_score = 1;
-
- if ((e_turret.target_select_playerbias > 0) && (e_target.flags & FL_CLIENT))
- 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 * e_turret.target_select_rangebias) +
- (a_score * e_turret.target_select_anglebias) +
- (m_score * e_turret.target_select_missilebias) +
- (p_score * e_turret.target_select_playerbias);
-
- if(e_turret.target_range < vlen(e_turret.tur_shotorg - real_origin(e_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 *= e_turret.target_select_rangebias;
- sdt = ftos(d_score);
-
- //sv = ftos(v_score);
- //v_score *= e_turret.target_select_samebias;
- //svt = ftos(v_score);
-
- sa = ftos(a_score);
- a_score *= e_turret.target_select_anglebias;
- sat = ftos(a_score);
-
- sm = ftos(m_score);
- m_score *= e_turret.target_select_missilebias;
- smt = ftos(m_score);
-
- sp = ftos(p_score);
- p_score *= e_turret.target_select_playerbias;
- spt = ftos(p_score);
-
-
- ss = ftos(score);
- bprint("^3Target scores^7 \[ ",e_turret.netname, " \] ^3for^7 \[ ", e_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;
-}
-
-/*
-float turret_stdproc_targetscore_close(entity e_turret,entity e_target)
-{
- return 1 - (tvt_dist / e_turret.target_range);
-}
-
-float turret_stdproc_targetscore_far (entity e_turret,entity e_target)
-{
- return tvt_dist / e_turret.target_range;
-}
-
-float turret_stdproc_targetscore_optimal(entity e_turret,entity e_target)
-{
- return min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist);
-}
-
-float turret_stdproc_score_angular(entity e_turret,entity e_target)
-{
- return 1 - (tvt_thadf / e_turret.aim_maxrot);
-}
-
-float turret_stdproc_targetscore_defend(entity e_turret,entity e_target)
-{
- return 0;
- //min(e_target.origin,e_turret.tur_defend.origin) / max(e_target.origin,e_turret.tur_defend.origin);
-}
-*/
+/*
+.float target_select_flags; /// target selection flags
+float TFL_TARGETSELECT_NO = 1; /// Dont select a target on its own.
+float TFL_TARGETSELECT_LOS = 2; /// Need line of sight
+float TFL_TARGETSELECT_PLAYERS = 4; /// Players are valid targets
+float TFL_TARGETSELECT_MISSILES = 8; /// Missiles are valid targets
+float TFL_TARGETSELECT_TRIGGERTARGET = 16; /// Responds to turret_trigger_target events
+float TFL_TARGETSELECT_ANGLELIMITS = 32; /// Angular limitations of turret head limits target selection
+float TFL_TARGETSELECT_RANGELIMTS = 64; /// Range limits apply in targetselection
+float TFL_TARGETSELECT_TEAMCHECK = 128; /// Consider team own <-> targets team
+float TFL_TARGETSELECT_NOBUILTIN = 256; /// Cant select targets on its own. needs to be triggerd or slaved.
+float TFL_TARGETSELECT_OWNTEAM = 512;
+*/
+
+float turret_stdproc_targetscore_support(entity e_turret,entity e_target)
+{
+ float score; // Total score
+ float s_score,d_score;
+
+ if (e_turret.enemy == e_target) s_score = 1;
+
+ d_score = min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist);
+
+ score = (d_score * e_turret.target_select_rangebias) +
+ (s_score * e_turret.target_select_samebias);
+
+ return score;
+}
+
+/*
+* Generic bias aware score system.
+*/
+float turret_stdproc_targetscore_generic(entity e_turret,entity e_target)
+{
+ //vector v_tmp;
+ float d_dist; // Defendmode Distance
+
+ float score; // Total score
+
+ float d_score; // Distance score
+ float a_score; // Angular score
+ float m_score; // missile score
+ float p_score; // player score
+ //float da_score; // Distance from aimpoint score
+
+ float ikr; // ideal kill range
+
+ if(!e_target) return 0;
+
+ //if (e_target == e_turret.enemy) s_score = 1;
+
+ if (e_turret.tur_defend)
+ {
+ d_dist = vlen(real_origin(e_target) - e_turret.tur_defend.origin);
+ ikr = vlen(e_turret.origin - e_turret.tur_defend.origin);
+ d_score = 1 - d_dist / e_turret.target_range;
+ }
+ else
+ {
+ // Make a normlized value base on the targets distance from our optimal killzone
+ ikr = e_turret.target_range_optimal;
+ d_score = min(ikr,tvt_dist) / max(ikr,tvt_dist);
+ }
+
+ /*
+ // Determine the maximum time it could take this turrent to aim at someting.
+ max_aim_delay = (max(e_turret.aim_maxrot,e_turret.aim_maxpitch) / e_turret.aim_speed * 2);
+
+ // Find out how long it would take to aim at this taget.
+ aim_delay = (thadf+0.01) / e_turret.aim_speed;
+
+ // Turn this info into a normalized value.
+ aim_delay = (min(max_aim_delay,aim_delay) / max_aim_delay);
+ a_score = 1 - aim_delay;
+ */
+
+ //a_score = 1 - (tvt_thadf / max(e_turret.aim_maxrot,e_turret.aim_maxpitch));
+ a_score = 1 - tvt_thadf / e_turret.aim_maxrot;
+
+ if ((e_turret.target_select_missilebias > 0) && (e_target.flags & FL_PROJECTILE))
+ m_score = 1;
+
+ if ((e_turret.target_select_playerbias > 0) && (e_target.flags & FL_CLIENT))
+ 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 * e_turret.target_select_rangebias) +
+ (a_score * e_turret.target_select_anglebias) +
+ (m_score * e_turret.target_select_missilebias) +
+ (p_score * e_turret.target_select_playerbias);
+
+ if(e_turret.target_range < vlen(e_turret.tur_shotorg - real_origin(e_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 *= e_turret.target_select_rangebias;
+ sdt = ftos(d_score);
+
+ //sv = ftos(v_score);
+ //v_score *= e_turret.target_select_samebias;
+ //svt = ftos(v_score);
+
+ sa = ftos(a_score);
+ a_score *= e_turret.target_select_anglebias;
+ sat = ftos(a_score);
+
+ sm = ftos(m_score);
+ m_score *= e_turret.target_select_missilebias;
+ smt = ftos(m_score);
+
+ sp = ftos(p_score);
+ p_score *= e_turret.target_select_playerbias;
+ spt = ftos(p_score);
+
+
+ ss = ftos(score);
+ bprint("^3Target scores^7 \[ ",e_turret.netname, " \] ^3for^7 \[ ", e_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;
+}
+
+/*
+float turret_stdproc_targetscore_close(entity e_turret,entity e_target)
+{
+ return 1 - (tvt_dist / e_turret.target_range);
+}
+
+float turret_stdproc_targetscore_far (entity e_turret,entity e_target)
+{
+ return tvt_dist / e_turret.target_range;
+}
+
+float turret_stdproc_targetscore_optimal(entity e_turret,entity e_target)
+{
+ return min(e_turret.target_range_optimal,tvt_dist) / max(e_turret.target_range_optimal,tvt_dist);
+}
+
+float turret_stdproc_score_angular(entity e_turret,entity e_target)
+{
+ return 1 - (tvt_thadf / e_turret.aim_maxrot);
+}
+
+float turret_stdproc_targetscore_defend(entity e_turret,entity e_target)
+{
+ return 0;
+ //min(e_target.origin,e_turret.tur_defend.origin) / max(e_target.origin,e_turret.tur_defend.origin);
+}
+*/
Property changes on: trunk/data/qcsrc/server/tturrets/system/system_scoreprocs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_checkpoint.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_checkpoint.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_checkpoint.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,70 +1,70 @@
-/**
- turret_checkpoint
-**/
-
-
-#define checkpoint_target goalstack03
-
-/*
-#define checkpoint_cache_who flagcarried
-#define checkpoint_cache_from lastrocket
-#define checkpoint_cache_to selected_player
-*/
-
-#define pathgoal goalstack01
-#define pathcurrent goalstack02
-
-/*
-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()
-{
-}
-
-/*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.
-*/
-void turret_checkpoint_init()
-{
- traceline(self.origin, self.origin - '0 0 1024', MOVE_WORLDONLY, self);
- setorigin(self,trace_endpos + '0 0 8');
-
- if(self.target != "")
- {
- self.enemy = find(world,targetname,self.target);
- if(self.enemy == world)
- dprint("A turret_checkpoint faild to find its target!\n");
- }
-}
-
-void spawnfunc_turret_checkpoint()
-{
- setorigin(self,self.origin);
- self.think = turret_checkpoint_init;
- self.nextthink = time + 0.1;
-}
-
-// Compat.
-void spawnfunc_walker_checkpoint()
-{
- self.classname = "turret_checkpoint";
- spawnfunc_turret_checkpoint();
-}
+/**
+ turret_checkpoint
+**/
+
+
+#define checkpoint_target goalstack03
+
+/*
+#define checkpoint_cache_who flagcarried
+#define checkpoint_cache_from lastrocket
+#define checkpoint_cache_to selected_player
+*/
+
+#define pathgoal goalstack01
+#define pathcurrent goalstack02
+
+/*
+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()
+{
+}
+
+/*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.
+*/
+void turret_checkpoint_init()
+{
+ traceline(self.origin, self.origin - '0 0 1024', MOVE_WORLDONLY, self);
+ setorigin(self,trace_endpos + '0 0 8');
+
+ if(self.target != "")
+ {
+ self.enemy = find(world,targetname,self.target);
+ if(self.enemy == world)
+ dprint("A turret_checkpoint faild to find its target!\n");
+ }
+}
+
+void spawnfunc_turret_checkpoint()
+{
+ setorigin(self,self.origin);
+ self.think = turret_checkpoint_init;
+ self.nextthink = time + 0.1;
+}
+
+// Compat.
+void spawnfunc_walker_checkpoint()
+{
+ self.classname = "turret_checkpoint";
+ spawnfunc_turret_checkpoint();
+}
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_checkpoint.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_common.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_common.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_common.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1 +1 @@
-
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_common.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,520 +1,520 @@
-void turret_ewheel_projectile_explode()
-{
- vector org2;
-
- org2 = findbetterlocation (self.origin, 8);
- pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1);
- //w_deathtypestring = "saw the eweel. to late.";
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-#endif
- sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
-
- remove (self);
-}
-
-
-void ewheel_attack()
-{
- entity proj;
- float i;
-
- for (i=0;i<1;++i)
- {
- turret_do_updates(self);
-
- sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM);
- pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- //setsize(proj, '-0.5 -0.5 -0.5', '0.5 0.5 0.5');
- //setmodel(proj, "models/laser.mdl"); // precision set above
- proj.classname = "ewheel bolt";
- proj.owner = self;
- proj.bot_dodge = FALSE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_ewheel_projectile_explode;
- proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.angles = vectoangles(proj.velocity);
- proj.touch = turret_ewheel_projectile_explode;
- //proj.effects = EF_LOWPRECISION | EF_BRIGHTFIELD;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);
-
- self.tur_head.frame += 2;
-
- if (self.tur_head.frame > 3)
- self.tur_head.frame = 0;
- }
-
-}
-
-float ewheel_moveverb_roam(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (!self.enemy)
- return verb.verb_static_value;
-
- return VS_CALL_NO;
-
- case VCM_DO:
- self.angles_z = 0;
- makevectors(self.angles);
- self.moveto = v_forward * 128;
- self.steerto = steerlib_beamsteer(v_forward,1024,32,36,128);
- self.frame += 1;
- movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
-
- return VS_CALL_YES_DOING;
-
- case VCM_REMOVE:
-
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float ewheel_moveverb_path(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.pathcurrent)
- return verb.verb_static_value;
-
- return VS_CALL_NO;
-
- case VCM_DO:
- // Do we have a path?
- if not(self.pathcurrent)
- return VS_CALL_NO;
- else
- {
- // 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;
- }
-
-
- if (self.pathcurrent)
- {
- switch (self.waterlevel)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- }
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
-
- self.frame += 1;
- movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
-
- return VS_CALL_YES_DOING;
- }
- else
- return VS_CALL_YES_DONE;
-
- case VCM_REMOVE:
-
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-
- self.pathcurrent = world;
-
- return VS_CALL_YES_DONE;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float ewheel_moveverb_enemy(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if (self.enemy)
- {
- if (self.spawnflags & TSF_NO_PATHBREAK)
- if (self.pathcurrent)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
- }
-
- return VS_CALL_NO;
-
- case VCM_DO:
-
- self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
- self.steerto = steerlib_beamsteer(self.steerto,1024,64,68,256);
- self.moveto = self.origin + self.steerto * 128;
-
- makevectors(self.angles);
-
- if (self.tur_dist_enemy > self.target_range_optimal)
- {
- if ( self.tur_head.spawnshieldtime < 1 )
- {
- self.frame += 2;
- movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
- }
- else if (self.tur_head.spawnshieldtime < 2)
- {
-
- self.frame += 1;
- movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);
- }
- else
- {
- self.frame += 1;
- movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slower"),0.4);
- }
- }
- else if (self.tur_dist_enemy < self.target_range_min)
- {
- self.frame -= 1;
- movelib_move_simple(v_forward * -1,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);
- }
- else
- {
- movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));
- }
-
- return VS_CALL_YES_DOING;
- }
-
-
- return VS_CALL_YES_DONE;
-}
-
-float ewheel_moveverb_runaway(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if (self.spawnflags & TSF_NO_PATHBREAK)
- if (self.pathcurrent)
- return VS_CALL_NO;
-
- if (self.enemy)
- if (self.health < 50)
- return verb.verb_static_value;
-
- return VS_CALL_NO;
-
- case VCM_DO:
- self.steerto = (steerlib_push(self.enemy.origin) * 0.7) + (steerlib_traceavoid_flat(0.3, 500, '0 0 128') * 0.3);
- self.moveto = self.origin + self.steerto * 1000;
-
- self.frame += 2;
- movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
-
- return VS_CALL_YES_DOING;
-
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float ewheel_moveverb_idle(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if (self.enemy)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
- self.moveto = self.origin;
-
- if (vlen(self.velocity))
- movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-void ewheel_postthink()
-{
- 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);
-
- self.angles_x *= -1;
- makevectors(self.angles);
- self.angles_x *= -1;
-
- 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);
-
- // Simulate banking
- self.angles_z = bound(-45,real_angle_y * -2.5,45);
-
- verbstack_pop(self.verbs_move);
-
- if (self.frame > 40)
- self.frame = 1;
-
- if (self.frame < 1)
- self.frame = 40;
-
-
- self.velocity_z = vz;
-}
-
-void ewheel_respawnhook()
-{
- entity e;
-
- 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
- {
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
- }
- }
-}
-
-void ewheel_diehook()
-{
- turret_trowgib2(self.origin,self.velocity + v_up * 400,'-0.6 -0.2 -02',self,time + random() * 2 +3);
-
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-
- self.pathcurrent = world;
-
- if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
- {
- verbstack_flush(self.verbs_move);
- remove(self.verbs_move);
- }
-
-}
-
-/*
-float test_stack_1(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- return verb.verb_static_value;
-
- case VCM_DO:
- dprint("test_stack_1\n");
- return VS_CALL_REMOVE;
- }
-
- return VS_CALL_REMOVE;
-}
-
-float test_stack_2(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- return verb.verb_static_value;
-
- case VCM_DO:
- dprint("test_stack_2\n");
- return VS_CALL_REMOVE;
- }
-
- return VS_CALL_REMOVE;
-}
-
-float ccnntt;
-float test_stack_3(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- return verb.verb_static_value;
-
- case VCM_DO:
- dprint("test_stack_3\n");
- ++ccnntt;
- if(ccnntt > 3)
- return VS_CALL_REMOVE;
- else
- return VS_CALL_YES_DONE;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-.entity test_stack;
-*/
-void turret_ewheel_dinit()
-{
- entity e;
-
- if (self.netname == "") self.netname = "eWheel Turret";
-
- if (self.target != "")
- {
- e = find(world,targetname,self.target);
- if (!e)
- {
- bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- self.goalcurrent = e;
- }
-
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_HEADATTACHED;
- //self.aim_flags = TFL_AIM_SIMPLE;// TFL_AIM_LEAD | TFL_AIM_ZEASE;
-
- self.turret_respawnhook = ewheel_respawnhook;
- self.turret_diehook = ewheel_diehook;
-
- if (turret_stdproc_init("ewheel_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
- self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
-
- self.iscreature = TRUE;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
-
- setmodel(self,"models/turrets/ewheel-base.md3");
- setmodel(self.tur_head,"models/turrets/ewheel-gun1.md3");
- setattachment(self.tur_head,self,"tag_head");
-
- self.pos1 = self.origin;
-
- self.idle_aim = '0 0 0';
-
- // Our fire routine
- self.turret_firefunc = ewheel_attack;
- self.turret_postthink = ewheel_postthink;
- self.tur_head.frame = 1;
-
- self.verbs_move = spawn();
-
- //verbstack_push(self.verbs_move, ewheel_moveverb_roam, WVM_IDLE, 0, self);
- verbstack_push(self.verbs_move, ewheel_moveverb_idle, WVM_IDLE, 0, self);
- verbstack_push(self.verbs_move, ewheel_moveverb_enemy, WVM_ENEMY, 0, self);
- verbstack_push(self.verbs_move, ewheel_moveverb_path, WVM_PATH, 0, self);
- //verbstack_push(self.verbs_move, ewheel_moveverb_runaway,WVM_PANIC, 0, self);
-
- /*
- self.test_stack = spawn();
- verbstack_push(self.test_stack, test_stack_1,1, 0, self);
- verbstack_push(self.test_stack, test_stack_2,2, 0, self);
- verbstack_push(self.test_stack, test_stack_3,100,0, self);
- while(verbstack_popfifo(self.test_stack) != 0)
- */
-
-
-
- // Convert from dgr / sec to dgr / tic
- self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");
- self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
-
- 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
- {
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
- }
- }
-}
-
-void spawnfunc_turret_ewheel()
-{
- g_turrets_common_precash();
-
- precache_model ("models/turrets/ewheel-base.md3");
- precache_model ("models/turrets/ewheel-gun1.md3");
-
- self.think = turret_ewheel_dinit;
- self.nextthink = time + 0.5;
-}
+void turret_ewheel_projectile_explode()
+{
+ vector org2;
+
+ org2 = findbetterlocation (self.origin, 8);
+ pointparticles(particleeffectnum("laser_impact"), org2, trace_plane_normal * 1000, 1);
+ //w_deathtypestring = "saw the eweel. to late.";
+#ifdef TURRET_DEBUG
+ float d;
+
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+#endif
+ sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
+
+ remove (self);
+}
+
+
+void ewheel_attack()
+{
+ entity proj;
+ float i;
+
+ for (i=0;i<1;++i)
+ {
+ turret_do_updates(self);
+
+ sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", VOL_BASE, ATTN_NORM);
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ //setsize(proj, '-0.5 -0.5 -0.5', '0.5 0.5 0.5');
+ //setmodel(proj, "models/laser.mdl"); // precision set above
+ proj.classname = "ewheel bolt";
+ proj.owner = self;
+ proj.bot_dodge = FALSE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_ewheel_projectile_explode;
+ proj.nextthink = time + 9;
+ proj.solid = SOLID_BBOX;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ proj.angles = vectoangles(proj.velocity);
+ proj.touch = turret_ewheel_projectile_explode;
+ //proj.effects = EF_LOWPRECISION | EF_BRIGHTFIELD;
+ proj.enemy = self.enemy;
+ proj.flags = FL_PROJECTILE | FL_NOTARGET;
+
+ CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);
+
+ self.tur_head.frame += 2;
+
+ if (self.tur_head.frame > 3)
+ self.tur_head.frame = 0;
+ }
+
+}
+
+float ewheel_moveverb_roam(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (!self.enemy)
+ return verb.verb_static_value;
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+ self.angles_z = 0;
+ makevectors(self.angles);
+ self.moveto = v_forward * 128;
+ self.steerto = steerlib_beamsteer(v_forward,1024,32,36,128);
+ self.frame += 1;
+ movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
+
+ return VS_CALL_YES_DOING;
+
+ case VCM_REMOVE:
+
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float ewheel_moveverb_path(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.pathcurrent)
+ return verb.verb_static_value;
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+ // Do we have a path?
+ if not(self.pathcurrent)
+ return VS_CALL_NO;
+ else
+ {
+ // 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;
+ }
+
+
+ if (self.pathcurrent)
+ {
+ switch (self.waterlevel)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ }
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+
+ self.frame += 1;
+ movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
+
+ return VS_CALL_YES_DOING;
+ }
+ else
+ return VS_CALL_YES_DONE;
+
+ case VCM_REMOVE:
+
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+
+ self.pathcurrent = world;
+
+ return VS_CALL_YES_DONE;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float ewheel_moveverb_enemy(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if (self.enemy)
+ {
+ if (self.spawnflags & TSF_NO_PATHBREAK)
+ if (self.pathcurrent)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+ }
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+
+ self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+ self.steerto = steerlib_beamsteer(self.steerto,1024,64,68,256);
+ self.moveto = self.origin + self.steerto * 128;
+
+ makevectors(self.angles);
+
+ if (self.tur_dist_enemy > self.target_range_optimal)
+ {
+ if ( self.tur_head.spawnshieldtime < 1 )
+ {
+ self.frame += 2;
+ movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
+ }
+ else if (self.tur_head.spawnshieldtime < 2)
+ {
+
+ self.frame += 1;
+ movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);
+ }
+ else
+ {
+ self.frame += 1;
+ movelib_move_simple(v_forward,cvar("g_turrets_unit_ewheel_speed_slower"),0.4);
+ }
+ }
+ else if (self.tur_dist_enemy < self.target_range_min)
+ {
+ self.frame -= 1;
+ movelib_move_simple(v_forward * -1,cvar("g_turrets_unit_ewheel_speed_slow"),0.4);
+ }
+ else
+ {
+ movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));
+ }
+
+ return VS_CALL_YES_DOING;
+ }
+
+
+ return VS_CALL_YES_DONE;
+}
+
+float ewheel_moveverb_runaway(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if (self.spawnflags & TSF_NO_PATHBREAK)
+ if (self.pathcurrent)
+ return VS_CALL_NO;
+
+ if (self.enemy)
+ if (self.health < 50)
+ return verb.verb_static_value;
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+ self.steerto = (steerlib_push(self.enemy.origin) * 0.7) + (steerlib_traceavoid_flat(0.3, 500, '0 0 128') * 0.3);
+ self.moveto = self.origin + self.steerto * 1000;
+
+ self.frame += 2;
+ movelib_move_simple(v_forward ,cvar("g_turrets_unit_ewheel_speed_fast"),0.4);
+
+ return VS_CALL_YES_DOING;
+
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float ewheel_moveverb_idle(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if (self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ self.moveto = self.origin;
+
+ if (vlen(self.velocity))
+ movelib_beak_simple(cvar("g_turrets_unit_ewheel_speed_stop"));
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void ewheel_postthink()
+{
+ 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);
+
+ self.angles_x *= -1;
+ makevectors(self.angles);
+ self.angles_x *= -1;
+
+ 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);
+
+ // Simulate banking
+ self.angles_z = bound(-45,real_angle_y * -2.5,45);
+
+ verbstack_pop(self.verbs_move);
+
+ if (self.frame > 40)
+ self.frame = 1;
+
+ if (self.frame < 1)
+ self.frame = 40;
+
+
+ self.velocity_z = vz;
+}
+
+void ewheel_respawnhook()
+{
+ entity e;
+
+ 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
+ {
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+ }
+ }
+}
+
+void ewheel_diehook()
+{
+ turret_trowgib2(self.origin,self.velocity + v_up * 400,'-0.6 -0.2 -02',self,time + random() * 2 +3);
+
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+
+ self.pathcurrent = world;
+
+ if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
+ {
+ verbstack_flush(self.verbs_move);
+ remove(self.verbs_move);
+ }
+
+}
+
+/*
+float test_stack_1(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ dprint("test_stack_1\n");
+ return VS_CALL_REMOVE;
+ }
+
+ return VS_CALL_REMOVE;
+}
+
+float test_stack_2(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ dprint("test_stack_2\n");
+ return VS_CALL_REMOVE;
+ }
+
+ return VS_CALL_REMOVE;
+}
+
+float ccnntt;
+float test_stack_3(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ dprint("test_stack_3\n");
+ ++ccnntt;
+ if(ccnntt > 3)
+ return VS_CALL_REMOVE;
+ else
+ return VS_CALL_YES_DONE;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+.entity test_stack;
+*/
+void turret_ewheel_dinit()
+{
+ entity e;
+
+ if (self.netname == "") self.netname = "eWheel Turret";
+
+ if (self.target != "")
+ {
+ e = find(world,targetname,self.target);
+ if (!e)
+ {
+ bprint("Warning! initital waypoint for ewheel does NOT exsist!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ self.goalcurrent = e;
+ }
+
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+ self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_HEADATTACHED;
+ //self.aim_flags = TFL_AIM_SIMPLE;// TFL_AIM_LEAD | TFL_AIM_ZEASE;
+
+ self.turret_respawnhook = ewheel_respawnhook;
+ self.turret_diehook = ewheel_diehook;
+
+ if (turret_stdproc_init("ewheel_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
+ self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
+
+ self.iscreature = TRUE;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+
+ setmodel(self,"models/turrets/ewheel-base.md3");
+ setmodel(self.tur_head,"models/turrets/ewheel-gun1.md3");
+ setattachment(self.tur_head,self,"tag_head");
+
+ self.pos1 = self.origin;
+
+ self.idle_aim = '0 0 0';
+
+ // Our fire routine
+ self.turret_firefunc = ewheel_attack;
+ self.turret_postthink = ewheel_postthink;
+ self.tur_head.frame = 1;
+
+ self.verbs_move = spawn();
+
+ //verbstack_push(self.verbs_move, ewheel_moveverb_roam, WVM_IDLE, 0, self);
+ verbstack_push(self.verbs_move, ewheel_moveverb_idle, WVM_IDLE, 0, self);
+ verbstack_push(self.verbs_move, ewheel_moveverb_enemy, WVM_ENEMY, 0, self);
+ verbstack_push(self.verbs_move, ewheel_moveverb_path, WVM_PATH, 0, self);
+ //verbstack_push(self.verbs_move, ewheel_moveverb_runaway,WVM_PANIC, 0, self);
+
+ /*
+ self.test_stack = spawn();
+ verbstack_push(self.test_stack, test_stack_1,1, 0, self);
+ verbstack_push(self.test_stack, test_stack_2,2, 0, self);
+ verbstack_push(self.test_stack, test_stack_3,100,0, self);
+ while(verbstack_popfifo(self.test_stack) != 0)
+ */
+
+
+
+ // Convert from dgr / sec to dgr / tic
+ self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");
+ self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
+
+ 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
+ {
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+ }
+ }
+}
+
+void spawnfunc_turret_ewheel()
+{
+ g_turrets_common_precash();
+
+ precache_model ("models/turrets/ewheel-base.md3");
+ precache_model ("models/turrets/ewheel-gun1.md3");
+
+ self.think = turret_ewheel_dinit;
+ self.nextthink = time + 0.5;
+}
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_ewheel.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_flac.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_flac.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_flac.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,128 +1,128 @@
-void spawnfunc_turret_flac();
-void turret_flac_dinit();
-void turret_flac_attack();
-void turret_flac_projectile_explode();
-
-void turret_flac_attack()
-{
- local entity proj;
-
- turret_tag_fire_update();
-
- sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- // setmodel(proj, "models/turrets/pd_proj.md3");
- setsize(proj, '0 0 0', '0 0 0');
- proj.classname = "flac_projectile";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.flags = FL_PROJECTILE;
- // proj.effects = EF_LOWPRECISION;
- proj.takedamage = DAMAGE_NO;
- //proj.health = 100;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- proj.angles = vectoangles(proj.velocity);
- proj.touch = turret_flac_projectile_explode;
- proj.think = turret_flac_projectile_explode;
- //proj.nextthink = time + vlen(self.tur_shotorg - self.enemy.origin) / self.shot_speed;
- proj.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 3) / self.shot_speed);
- proj.enemy = self.enemy;
- proj.cnt = time + 5;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_HAGAR, TRUE);
-
- self.tur_head.frame = self.tur_head.frame + 1;
- if (self.tur_head.frame >= 4) self.tur_head.frame = 0;
-
-}
-
-void turret_flac_projectile_explode()
-{
- float ftmp;
-
- // FIXME: tur_impacttime is not accurate enougth, this is a dirty hakk to make flac work.
-
- //w_deathtypestring = "got caught in the flack.";
-
-
-
- if( (self.enemy != world) &&
- (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3) )
- {
- // OMG HAXX!
- setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
- }
-
-
-
- te_explosion (self.origin);
-
- ftmp = crandom();
- if (ftmp<-0.7)
- sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM);
- else if (ftmp<0.4)
- sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM);
- else if (ftmp<1)
- sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
-
-
- self.event_damage = SUB_Null;
-
-
-#ifdef TURRET_DEBUG
- ftmp = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + ftmp; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-#endif
-
- remove (self);
-}
-
-
-void turret_flac_dinit()
-{
- if (self.netname == "") self.netname = "FLAC Cannon";
-
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_MISSILEKILL;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
- if (turret_stdproc_init("flac_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/flac.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fire routine
- self.turret_firefunc = turret_flac_attack;
-
-}
-/*QUAKED turret_flac (0 .5 .8) ?
-*/
-
-void spawnfunc_turret_flac()
-{
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/flac.md3");
- //precache_model("models/turrets/pd_proj.md3");
-
- self.think = turret_flac_dinit;
- self.nextthink = time + 0.5;
-}
-
+void spawnfunc_turret_flac();
+void turret_flac_dinit();
+void turret_flac_attack();
+void turret_flac_projectile_explode();
+
+void turret_flac_attack()
+{
+ local entity proj;
+
+ turret_tag_fire_update();
+
+ sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ // setmodel(proj, "models/turrets/pd_proj.md3");
+ setsize(proj, '0 0 0', '0 0 0');
+ proj.classname = "flac_projectile";
+ proj.owner = self;
+ proj.bot_dodge = TRUE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.solid = SOLID_BBOX;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.flags = FL_PROJECTILE;
+ // proj.effects = EF_LOWPRECISION;
+ proj.takedamage = DAMAGE_NO;
+ //proj.health = 100;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ proj.angles = vectoangles(proj.velocity);
+ proj.touch = turret_flac_projectile_explode;
+ proj.think = turret_flac_projectile_explode;
+ //proj.nextthink = time + vlen(self.tur_shotorg - self.enemy.origin) / self.shot_speed;
+ proj.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 3) / self.shot_speed);
+ proj.enemy = self.enemy;
+ proj.cnt = time + 5;
+
+ CSQCProjectile(proj, TRUE, PROJECTILE_HAGAR, TRUE);
+
+ self.tur_head.frame = self.tur_head.frame + 1;
+ if (self.tur_head.frame >= 4) self.tur_head.frame = 0;
+
+}
+
+void turret_flac_projectile_explode()
+{
+ float ftmp;
+
+ // FIXME: tur_impacttime is not accurate enougth, this is a dirty hakk to make flac work.
+
+ //w_deathtypestring = "got caught in the flack.";
+
+
+
+ if( (self.enemy != world) &&
+ (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3) )
+ {
+ // OMG HAXX!
+ setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+ }
+
+
+
+ te_explosion (self.origin);
+
+ ftmp = crandom();
+ if (ftmp<-0.7)
+ sound (self, CHAN_PROJECTILE, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM);
+ else if (ftmp<0.4)
+ sound (self, CHAN_PROJECTILE, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM);
+ else if (ftmp<1)
+ sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
+
+
+ self.event_damage = SUB_Null;
+
+
+#ifdef TURRET_DEBUG
+ ftmp = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + ftmp; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+#endif
+
+ remove (self);
+}
+
+
+void turret_flac_dinit()
+{
+ if (self.netname == "") self.netname = "FLAC Cannon";
+
+
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_MISSILEKILL;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ if (turret_stdproc_init("flac_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/flac.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fire routine
+ self.turret_firefunc = turret_flac_attack;
+
+}
+/*QUAKED turret_flac (0 .5 .8) ?
+*/
+
+void spawnfunc_turret_flac()
+{
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/flac.md3");
+ //precache_model("models/turrets/pd_proj.md3");
+
+ self.think = turret_flac_dinit;
+ self.nextthink = time + 0.5;
+}
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_flac.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_fusionreactor.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_fusionreactor.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_fusionreactor.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,83 +1,83 @@
-void spawnfunc_turret_fusionreactor();
-void turret_fusionreactor_dinit();
-void turret_fusionreactor_fire();
-
-float turret_fusionreactor_firecheck()
-{
- if (self.enemy == world) return 0;
-
- if (!self.enemy.ammo_flags & TFL_AMMO_RECIVE) return 0;
- if (!self.enemy.ammo_flags & TFL_AMMO_ENERGY) return 0;
-
- if (self.ammo < self.shot_dmg) return 0;
- if (self.enemy.ammo >= self.enemy.ammo_max) return 0;
- if (self.tur_dist_aimpos > self.target_range) return 0;
- if (self.tur_dist_aimpos < self.target_range_min) return 0;
-
- return 1;
-}
-
-
-void turret_fusionreactor_fire()
-{
- self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
- //te_lightning1(world,self.origin,self.enemy.origin);
-}
-
-void turret_fusionreactor_postthink()
-{
-}
-
-void turret_fusionreactor_respawnhook()
-{
- self.tur_head.avelocity = '0 50 0';
-}
-
-void turret_fusionreactor_dinit()
-{
- if (self.netname == "") self.netname = "Fusionreactor";
-
- self.turrcaps_flags = TFL_TURRCAPS_SUPPORT | TFL_TURRCAPS_AMMOSOURCE;
-
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
-
- self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMTS;
-
- self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_WORLD;
-
- self.shoot_flags = TFL_SHOOT_HITALLVALID;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
- self.turret_respawnhook = turret_fusionreactor_respawnhook;
- if (turret_stdproc_init("fusreac_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/reactor.md3");
-
- //if(!turret_tag_setup())
- // dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- self.tur_head.scale = 0.75;
- setorigin(self.tur_head,self.origin + '0 0 25');
- self.tur_head.avelocity = '0 50 0';
-
- self.turret_firecheckfunc = turret_fusionreactor_firecheck;
- self.turret_firefunc = turret_fusionreactor_fire;
-
- self.turret_postthink = turret_fusionreactor_postthink;
-}
-
-/*QUAKED turret_fusionreactor (0 .5 .8) ?
-*/
-void spawnfunc_turret_fusionreactor()
-{
- precache_model ("models/turrets/reactor.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_fusionreactor_dinit;
- self.nextthink = time + 0.5;
-}
+void spawnfunc_turret_fusionreactor();
+void turret_fusionreactor_dinit();
+void turret_fusionreactor_fire();
+
+float turret_fusionreactor_firecheck()
+{
+ if (self.enemy == world) return 0;
+
+ if (!self.enemy.ammo_flags & TFL_AMMO_RECIVE) return 0;
+ if (!self.enemy.ammo_flags & TFL_AMMO_ENERGY) return 0;
+
+ if (self.ammo < self.shot_dmg) return 0;
+ if (self.enemy.ammo >= self.enemy.ammo_max) return 0;
+ if (self.tur_dist_aimpos > self.target_range) return 0;
+ if (self.tur_dist_aimpos < self.target_range_min) return 0;
+
+ return 1;
+}
+
+
+void turret_fusionreactor_fire()
+{
+ self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+ //te_lightning1(world,self.origin,self.enemy.origin);
+}
+
+void turret_fusionreactor_postthink()
+{
+}
+
+void turret_fusionreactor_respawnhook()
+{
+ self.tur_head.avelocity = '0 50 0';
+}
+
+void turret_fusionreactor_dinit()
+{
+ if (self.netname == "") self.netname = "Fusionreactor";
+
+ self.turrcaps_flags = TFL_TURRCAPS_SUPPORT | TFL_TURRCAPS_AMMOSOURCE;
+
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+
+ self.target_select_flags = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMTS;
+
+ self.firecheck_flags = TFL_FIRECHECK_OWM_AMMO | TFL_FIRECHECK_OTHER_AMMO | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_WORLD;
+
+ self.shoot_flags = TFL_SHOOT_HITALLVALID;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+ self.turret_respawnhook = turret_fusionreactor_respawnhook;
+ if (turret_stdproc_init("fusreac_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/reactor.md3");
+
+ //if(!turret_tag_setup())
+ // dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ self.tur_head.scale = 0.75;
+ setorigin(self.tur_head,self.origin + '0 0 25');
+ self.tur_head.avelocity = '0 50 0';
+
+ self.turret_firecheckfunc = turret_fusionreactor_firecheck;
+ self.turret_firefunc = turret_fusionreactor_fire;
+
+ self.turret_postthink = turret_fusionreactor_postthink;
+}
+
+/*QUAKED turret_fusionreactor (0 .5 .8) ?
+*/
+void spawnfunc_turret_fusionreactor()
+{
+ precache_model ("models/turrets/reactor.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_fusionreactor_dinit;
+ self.nextthink = time + 0.5;
+}
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_fusionreactor.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_hellion.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_hellion.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_hellion.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,222 +1,222 @@
-.float shot_speed_max;
-.float shot_speed_gain;
-
-void spawnfunc_turret_hellion();
-void turret_hellion_dinit();
-void turret_hellion_attack();
-void turret_hellion_missile_explode();
-void turret_hellion_missile_think();
-void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-
-void turret_hellion_postthink()
-{
- if (cvar("g_turrets_reloadcvars"))
- {
- if (!self.shot_speed_max) self.shot_speed_max = cvar("g_turrets_unit_hellion_std_shot_speed_max");
- if (!self.shot_speed_gain) self.shot_speed_gain = cvar("g_turrets_unit_hellion_std_shot_speed_gain");
- }
-
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
- if (self.tur_head.frame > 7)
- self.tur_head.frame = 0;
-}
-
-void turret_hellion_attack()
-{
- local entity missile;
-
- sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- setorigin(missile, self.tur_shotorg);
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
- missile.classname = "hellion_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_YES;
- missile.event_damage = turret_hellion_missile_damage;
- missile.damageforcescale = 2;
- missile.health = 10;
- missile.enemy = self.enemy;
- missile.think = turret_hellion_missile_think;
- missile.nextthink = time;// + 0.2;
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLY;
- missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- missile.angles = vectoangles(missile.velocity);
- missile.touch = turret_hellion_missile_explode;
- missile.flags = FL_PROJECTILE;
- missile.solid = SOLID_BBOX;
- missile.tur_health = time + 9;
- missile.tur_aimpos = randomvec() * 128;
- te_explosion (missile.origin);
-
- CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
-
- // switch tubes
- self.tur_shotorg_y = self.tur_shotorg_y * -1;
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
-}
-
-void turret_hellion_missile_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) turret_hellion_missile_explode();
-}
-
-void turret_hellion_missile_think()
-{
- vector olddir,newdir;
- vector pre_pos;
- float itime;
-
- self.nextthink = time + 0.05;
-
- olddir = normalize(self.velocity);
-
- if(self.tur_health < time)
- turret_hellion_missile_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_hellion_missile_explode();
-
- // Accelerate
- self.velocity = olddir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
-
- UpdateCSQCProjectile(self);
-
- return;
- }
-
- // Enemy in range?
- if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
- turret_hellion_missile_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;
-
- //pre_pos += randomvec() * 128; //self.tur_aimpos * (sin(32) * time) ;
-
- // 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
- self.velocity = newdir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
-
- if (itime < 0.05)
- self.think = turret_hellion_missile_explode;
-
- UpdateCSQCProjectile(self);
-}
-
-void turret_hellion_missile_explode()
-{
- vector org2;
- float d;
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_hellion_missile_explode;
- self.nextthink = time;
- return;
- }
-
- sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
- org2 = findbetterlocation (self.origin, 16);
-
- // LordHavoc: TE_TEI_BIGEXPLOSION
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, 78);
- WriteCoord (MSG_BROADCAST, org2_x);
- WriteCoord (MSG_BROADCAST, org2_y);
- WriteCoord (MSG_BROADCAST, org2_z);
-
- //w_deathtypestring = "could not dodge the twin missiles.";
- self.event_damage = SUB_Null;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-
-#ifdef TURRET_DEBUG
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#endif
-
- // Target dead, get another is still targeting the same.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
-
- remove (self);
-}
-
-void turret_hellion_dinit()
-{
- if (self.netname == "") self.netname = "Hellion Missile Turret";
-
- if (!self.shot_speed_max) self.shot_speed_max = cvar("g_turrets_unit_hellion_std_shot_speed_max");
- if (!self.shot_speed_gain) self.shot_speed_gain = cvar("g_turrets_unit_hellion_std_shot_speed_gain");
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
- self.aim_flags = TFL_AIM_SIMPLE;
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK ;
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
- if (turret_stdproc_init("hellion_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/hellion.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fire routine
- self.turret_firefunc = turret_hellion_attack;
-
- // Custom animations and sutch
- self.turret_postthink = turret_hellion_postthink;
-}
-
-/*QUAKED turret_hellion (0 .5 .8) ?
-*/
-void spawnfunc_turret_hellion()
-{
- //precache_model ( "models/turrets/mlrs_rocket.md3");
- precache_model ("models/turrets/hellion.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_hellion_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+.float shot_speed_max;
+.float shot_speed_gain;
+
+void spawnfunc_turret_hellion();
+void turret_hellion_dinit();
+void turret_hellion_attack();
+void turret_hellion_missile_explode();
+void turret_hellion_missile_think();
+void turret_hellion_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+
+void turret_hellion_postthink()
+{
+ if (cvar("g_turrets_reloadcvars"))
+ {
+ if (!self.shot_speed_max) self.shot_speed_max = cvar("g_turrets_unit_hellion_std_shot_speed_max");
+ if (!self.shot_speed_gain) self.shot_speed_gain = cvar("g_turrets_unit_hellion_std_shot_speed_gain");
+ }
+
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+ if (self.tur_head.frame > 7)
+ self.tur_head.frame = 0;
+}
+
+void turret_hellion_attack()
+{
+ local entity missile;
+
+ sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
+
+ missile = spawn ();
+ setorigin(missile, self.tur_shotorg);
+ setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+ missile.classname = "hellion_missile";
+ missile.owner = self;
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = self.shot_dmg;
+ missile.takedamage = DAMAGE_YES;
+ missile.event_damage = turret_hellion_missile_damage;
+ missile.damageforcescale = 2;
+ missile.health = 10;
+ missile.enemy = self.enemy;
+ missile.think = turret_hellion_missile_think;
+ missile.nextthink = time;// + 0.2;
+ missile.solid = SOLID_BBOX;
+ missile.movetype = MOVETYPE_FLY;
+ missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ missile.angles = vectoangles(missile.velocity);
+ missile.touch = turret_hellion_missile_explode;
+ missile.flags = FL_PROJECTILE;
+ missile.solid = SOLID_BBOX;
+ missile.tur_health = time + 9;
+ missile.tur_aimpos = randomvec() * 128;
+ te_explosion (missile.origin);
+
+ CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
+
+ // switch tubes
+ self.tur_shotorg_y = self.tur_shotorg_y * -1;
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+}
+
+void turret_hellion_missile_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) turret_hellion_missile_explode();
+}
+
+void turret_hellion_missile_think()
+{
+ vector olddir,newdir;
+ vector pre_pos;
+ float itime;
+
+ self.nextthink = time + 0.05;
+
+ olddir = normalize(self.velocity);
+
+ if(self.tur_health < time)
+ turret_hellion_missile_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_hellion_missile_explode();
+
+ // Accelerate
+ self.velocity = olddir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
+
+ UpdateCSQCProjectile(self);
+
+ return;
+ }
+
+ // Enemy in range?
+ if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+ turret_hellion_missile_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;
+
+ //pre_pos += randomvec() * 128; //self.tur_aimpos * (sin(32) * time) ;
+
+ // 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
+ self.velocity = newdir * min(vlen(self.velocity) * self.owner.shot_speed_gain,self.owner.shot_speed_max);
+
+ if (itime < 0.05)
+ self.think = turret_hellion_missile_explode;
+
+ UpdateCSQCProjectile(self);
+}
+
+void turret_hellion_missile_explode()
+{
+ vector org2;
+ float d;
+
+ if(self.event_damage != SUB_Null)
+ {
+ self.event_damage = SUB_Null;
+ self.think = turret_hellion_missile_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+ org2 = findbetterlocation (self.origin, 16);
+
+ // LordHavoc: TE_TEI_BIGEXPLOSION
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, 78);
+ WriteCoord (MSG_BROADCAST, org2_x);
+ WriteCoord (MSG_BROADCAST, org2_y);
+ WriteCoord (MSG_BROADCAST, org2_z);
+
+ //w_deathtypestring = "could not dodge the twin missiles.";
+ self.event_damage = SUB_Null;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+
+#ifdef TURRET_DEBUG
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#endif
+
+ // Target dead, get another is still targeting the same.
+ if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
+ self.owner.enemy = world;
+
+ remove (self);
+}
+
+void turret_hellion_dinit()
+{
+ if (self.netname == "") self.netname = "Hellion Missile Turret";
+
+ if (!self.shot_speed_max) self.shot_speed_max = cvar("g_turrets_unit_hellion_std_shot_speed_max");
+ if (!self.shot_speed_gain) self.shot_speed_gain = cvar("g_turrets_unit_hellion_std_shot_speed_gain");
+
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_FASTPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
+ self.aim_flags = TFL_AIM_SIMPLE;
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK ;
+ self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_OWM_AMMO;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+
+ if (turret_stdproc_init("hellion_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/hellion.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fire routine
+ self.turret_firefunc = turret_hellion_attack;
+
+ // Custom animations and sutch
+ self.turret_postthink = turret_hellion_postthink;
+}
+
+/*QUAKED turret_hellion (0 .5 .8) ?
+*/
+void spawnfunc_turret_hellion()
+{
+ //precache_model ( "models/turrets/mlrs_rocket.md3");
+ precache_model ("models/turrets/hellion.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_hellion_dinit;
+ self.nextthink = time + 0.5;
+}
+
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_hellion.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_hk.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_hk.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_hk.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,480 +1,480 @@
-//#define TURRET_DEBUG_HK
-
-#ifdef TURRET_DEBUG_HK
-.float atime;
-#endif
-
-void spawnfunc_turret_hk();
-void turret_hk_dinit();
-void turret_hk_attack();
-void turret_hk_missile_explode();
-void turret_hk_missile_think();
-void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
-float turret_hk_addtarget(entity e_target,entity e_sender);
-//void turret_hk_missile_touch();
-
-float hk_maxspeed;
-float hk_minspeed;
-float hk_accel;
-float hk_accel2;
-float hk_decel;
-
-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;
-}
-
-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 (e_target.flags & FL_CLIENT)
- {
- 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_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- if (attacker.team == self.team)
- damage *= 0.5;
-
- self.velocity += force;
-
- self.health -= damage;
-
- if (self.health <= 0)
- turret_hk_missile_explode();
-}
-
-void turret_hk_attack()
-{
- local entity missile;
- //local entity flash2;
-
- sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- missile.solid = SOLID_BBOX;
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
- setorigin(missile, self.tur_shotorg);
-
- missile.scale = 1;
- missile.classname = "hk_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_YES;
- missile.damageforcescale = 4;
- missile.health = 10;
- missile.think = turret_hk_missile_think;
- missile.event_damage = turret_hk_missile_damage;
- 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.touch = turret_hk_missile_explode; //turret_hk_missile_touch;
- missile.flags = FL_PROJECTILE;
- missile.enemy = self.enemy;
- missile.team = self.team;
- missile.cnt = time + 30;
- missile.ticrate = max(cvar("sys_ticrate"),0.05);
-
- CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, fly sound
-
- te_explosion (missile.origin);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = self.tur_head.frame + 1;
-
-}
-
-/*
-void turret_hk_missile_touch()
-{
- if(other == self.enemy)
- turret_hk_missile_explode();
- else
- {
- if(self.cnt < time)
- {
- self.cnt = time + 0.25;
- self.health = self.health - 5;
- if(self.health <= 0)
- turret_hk_missile_explode();
-
- }
- }
-}
-*/
-
-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_hk_missile_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
- {
- 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) || (ad > 4)) && (myspeed > hk_minspeed) )
- myspeed = max(myspeed * hk_decel,hk_minspeed);
-
- // Failry clear, accelerate.
- if ( (ff > 0.7) && (myspeed < hk_maxspeed) )
- myspeed = min(myspeed * hk_accel,hk_maxspeed);
-
- // 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 < hk_maxspeed)
- myspeed = min(myspeed * hk_accel2,hk_maxspeed);
-
- wishdir = ve;
- //wishdir = normalize(self.enemy.origin - (self.enemy.origin + self.enemy.velocity));
- }
-
- if ((myspeed > hk_minspeed) && (self.cnt > time))
- myspeed = min(myspeed * hk_accel2,hk_maxspeed);
-
- // Ranoutagazfish?
- if (self.cnt < time)
- {
- self.cnt = time + 0.25;
- self.nextthink = 0;
- self.movetype = MOVETYPE_BOUNCE;
- sound (self, CHAN_VOICE, "", 0.4 * VOL_BASE, ATTN_NORM);
- return;
- }
-
- // Calculate new heading
- olddir = normalize(self.velocity);
-
- newdir = normalize(olddir + wishdir * cvar("g_turrets_unit_hk_std_shot_speed_turnrate"));
-
- //fu = (1 / hk_maxspeed) * myspeed;
- //fd = fu - (0.75 - 0.25);
- //newdir = normalize(olddir + wishdir * fd);
-
- // 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);
-}
-
-void turret_hk_missile_explode()
-{
- vector org2;
- float d;
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_hk_missile_explode;
- self.nextthink = time;
- return;
- }
-
- if ((other == self.owner)||(other == self.owner.tur_head))
- return;
-
- //w_deathtypestring = "got hunted to extinction";
- //vector org2;
- sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
- org2 = findbetterlocation (self.origin, 16);
-
- // LordHavoc: TE_TEI_BIGEXPLOSION
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, 78);
- WriteCoord (MSG_BROADCAST, org2_x);
- WriteCoord (MSG_BROADCAST, org2_y);
- WriteCoord (MSG_BROADCAST, org2_z);
-
- self.event_damage = SUB_Null;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-
-#ifdef TURRET_DEBUG
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#endif
-
- // Target dead, get another is still targeting the same.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
-
- remove (self);
-}
-
-void turret_hk_postthink()
-{
- if (cvar("g_turrets_reloadcvars"))
- {
- hk_maxspeed = cvar("g_turrets_unit_hk_std_shot_speed_max");
- hk_minspeed = cvar("g_turrets_unit_hk_std_shot_speed");
- hk_accel = cvar("g_turrets_unit_hk_std_shot_speed_accel");
- hk_accel2 = cvar("g_turrets_unit_hk_std_shot_speed_accel2");
- hk_decel = cvar("g_turrets_unit_hk_std_shot_speed_decel");
- }
-
- 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;
-
-}
-
-void turret_hk_dinit()
-{
- if (self.netname == "") self.netname = "Hunter-killer turret";
-
- hk_maxspeed = cvar("g_turrets_unit_hk_std_shot_speed_max");
- hk_minspeed = cvar("g_turrets_unit_hk_std_shot_speed");
- hk_accel = cvar("g_turrets_unit_hk_std_shot_speed_accel");
- hk_accel2 = cvar("g_turrets_unit_hk_std_shot_speed_accel2");
- hk_decel = cvar("g_turrets_unit_hk_std_shot_speed_decel");
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_RECIVETARGETS;
-
- 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_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
-
- self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.shoot_flags = TFL_SHOOT_CLEARTARGET;
-
- if (turret_stdproc_init("hk_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/hk.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fire routine
- self.turret_firefunc = turret_hk_attack;
-
- // re-color badge & handle recoil effect
- self.turret_postthink = turret_hk_postthink;
-
- // What to do when reciveing foreign target data
- self.turret_addtarget = turret_hk_addtarget;
-}
-
-/*
-* Turret that fires Hunter-killer missiles.
-* Missiles seek their target and try to avoid obstacles. If target dies early, they
-* pick a new one on their own.
-*/
-
-/*QUAKED turret_hk (0 .5 .8) ?
-hunter-killer missiles.
-*/
-
-void spawnfunc_turret_hk()
-{
- //precache_model ( "models/turrets/hunter2.md3");
- precache_model ("models/turrets/base.md3");
- precache_model ("models/turrets/hk.md3");
-
- self.think = turret_hk_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+//#define TURRET_DEBUG_HK
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+void spawnfunc_turret_hk();
+void turret_hk_dinit();
+void turret_hk_attack();
+void turret_hk_missile_explode();
+void turret_hk_missile_think();
+void turret_hk_missile_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
+float turret_hk_addtarget(entity e_target,entity e_sender);
+//void turret_hk_missile_touch();
+
+float hk_maxspeed;
+float hk_minspeed;
+float hk_accel;
+float hk_accel2;
+float hk_decel;
+
+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;
+}
+
+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 (e_target.flags & FL_CLIENT)
+ {
+ 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_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (attacker.team == self.team)
+ damage *= 0.5;
+
+ self.velocity += force;
+
+ self.health -= damage;
+
+ if (self.health <= 0)
+ turret_hk_missile_explode();
+}
+
+void turret_hk_attack()
+{
+ local entity missile;
+ //local entity flash2;
+
+ sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
+
+ missile = spawn ();
+ missile.solid = SOLID_BBOX;
+ setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+ setorigin(missile, self.tur_shotorg);
+
+ missile.scale = 1;
+ missile.classname = "hk_missile";
+ missile.owner = self;
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = self.shot_dmg;
+ missile.takedamage = DAMAGE_YES;
+ missile.damageforcescale = 4;
+ missile.health = 10;
+ missile.think = turret_hk_missile_think;
+ missile.event_damage = turret_hk_missile_damage;
+ 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.touch = turret_hk_missile_explode; //turret_hk_missile_touch;
+ missile.flags = FL_PROJECTILE;
+ missile.enemy = self.enemy;
+ missile.team = self.team;
+ missile.cnt = time + 30;
+ missile.ticrate = max(cvar("sys_ticrate"),0.05);
+
+ CSQCProjectile(missile, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, fly sound
+
+ te_explosion (missile.origin);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = self.tur_head.frame + 1;
+
+}
+
+/*
+void turret_hk_missile_touch()
+{
+ if(other == self.enemy)
+ turret_hk_missile_explode();
+ else
+ {
+ if(self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.health = self.health - 5;
+ if(self.health <= 0)
+ turret_hk_missile_explode();
+
+ }
+ }
+}
+*/
+
+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_hk_missile_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
+ {
+ 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) || (ad > 4)) && (myspeed > hk_minspeed) )
+ myspeed = max(myspeed * hk_decel,hk_minspeed);
+
+ // Failry clear, accelerate.
+ if ( (ff > 0.7) && (myspeed < hk_maxspeed) )
+ myspeed = min(myspeed * hk_accel,hk_maxspeed);
+
+ // 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 < hk_maxspeed)
+ myspeed = min(myspeed * hk_accel2,hk_maxspeed);
+
+ wishdir = ve;
+ //wishdir = normalize(self.enemy.origin - (self.enemy.origin + self.enemy.velocity));
+ }
+
+ if ((myspeed > hk_minspeed) && (self.cnt > time))
+ myspeed = min(myspeed * hk_accel2,hk_maxspeed);
+
+ // Ranoutagazfish?
+ if (self.cnt < time)
+ {
+ self.cnt = time + 0.25;
+ self.nextthink = 0;
+ self.movetype = MOVETYPE_BOUNCE;
+ sound (self, CHAN_VOICE, "", 0.4 * VOL_BASE, ATTN_NORM);
+ return;
+ }
+
+ // Calculate new heading
+ olddir = normalize(self.velocity);
+
+ newdir = normalize(olddir + wishdir * cvar("g_turrets_unit_hk_std_shot_speed_turnrate"));
+
+ //fu = (1 / hk_maxspeed) * myspeed;
+ //fd = fu - (0.75 - 0.25);
+ //newdir = normalize(olddir + wishdir * fd);
+
+ // 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);
+}
+
+void turret_hk_missile_explode()
+{
+ vector org2;
+ float d;
+
+ if(self.event_damage != SUB_Null)
+ {
+ self.event_damage = SUB_Null;
+ self.think = turret_hk_missile_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if ((other == self.owner)||(other == self.owner.tur_head))
+ return;
+
+ //w_deathtypestring = "got hunted to extinction";
+ //vector org2;
+ sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+ org2 = findbetterlocation (self.origin, 16);
+
+ // LordHavoc: TE_TEI_BIGEXPLOSION
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, 78);
+ WriteCoord (MSG_BROADCAST, org2_x);
+ WriteCoord (MSG_BROADCAST, org2_y);
+ WriteCoord (MSG_BROADCAST, org2_z);
+
+ self.event_damage = SUB_Null;
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+
+#ifdef TURRET_DEBUG
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#endif
+
+ // Target dead, get another is still targeting the same.
+ if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
+ self.owner.enemy = world;
+
+ remove (self);
+}
+
+void turret_hk_postthink()
+{
+ if (cvar("g_turrets_reloadcvars"))
+ {
+ hk_maxspeed = cvar("g_turrets_unit_hk_std_shot_speed_max");
+ hk_minspeed = cvar("g_turrets_unit_hk_std_shot_speed");
+ hk_accel = cvar("g_turrets_unit_hk_std_shot_speed_accel");
+ hk_accel2 = cvar("g_turrets_unit_hk_std_shot_speed_accel2");
+ hk_decel = cvar("g_turrets_unit_hk_std_shot_speed_decel");
+ }
+
+ 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;
+
+}
+
+void turret_hk_dinit()
+{
+ if (self.netname == "") self.netname = "Hunter-killer turret";
+
+ hk_maxspeed = cvar("g_turrets_unit_hk_std_shot_speed_max");
+ hk_minspeed = cvar("g_turrets_unit_hk_std_shot_speed");
+ hk_accel = cvar("g_turrets_unit_hk_std_shot_speed_accel");
+ hk_accel2 = cvar("g_turrets_unit_hk_std_shot_speed_accel2");
+ hk_decel = cvar("g_turrets_unit_hk_std_shot_speed_decel");
+
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_RECIVETARGETS;
+
+ 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_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+
+ self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.shoot_flags = TFL_SHOOT_CLEARTARGET;
+
+ if (turret_stdproc_init("hk_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/hk.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fire routine
+ self.turret_firefunc = turret_hk_attack;
+
+ // re-color badge & handle recoil effect
+ self.turret_postthink = turret_hk_postthink;
+
+ // What to do when reciveing foreign target data
+ self.turret_addtarget = turret_hk_addtarget;
+}
+
+/*
+* Turret that fires Hunter-killer missiles.
+* Missiles seek their target and try to avoid obstacles. If target dies early, they
+* pick a new one on their own.
+*/
+
+/*QUAKED turret_hk (0 .5 .8) ?
+hunter-killer missiles.
+*/
+
+void spawnfunc_turret_hk()
+{
+ //precache_model ( "models/turrets/hunter2.md3");
+ precache_model ("models/turrets/base.md3");
+ precache_model ("models/turrets/hk.md3");
+
+ self.think = turret_hk_dinit;
+ self.nextthink = time + 0.5;
+}
+
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_hk.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_machinegun.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_machinegun.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_machinegun.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,81 +1,81 @@
-void spawnfunc_turret_machinegun();
-void turret_machinegun_std_init();
-void turret_machinegun_attack();
-
-//.float bulletcounter;
-void turret_machinegun_attack()
-{
-
- entity flash;
-
- sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, cvar("g_balance_uzi_bulletconstant"));
-
- //w_deathtypestring = "had an alergic reaction due to 10 kilos of led";
- te_smallflash(self.tur_shotorg);
- // trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
-
- // muzzle flash for 3rd person view
- flash = spawn();
- //setorigin(flash, '43 1 8');
- setmodel(flash, "models/uziflash.md3"); // precision set below
- setattachment(flash, self.tur_head, "tag_fire");
- flash.think = W_Uzi_Flash_Go;
- flash.nextthink = time + 0.02;
- flash.frame = 2;
- flash.angles_z = flash.v_angle_z + random() * 180;
- flash.alpha = 1;
- flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-}
-
-
-void turret_machinegun_std_init()
-{
- if (self.netname == "") self.netname = "Machinegun Turret";
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL;// | TFL_TURRCAPS_MISSILEKILL;
- self.aim_flags = TFL_AIM_LEAD;
-
- if(cvar("g_antilag_bullets"))
- self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
- else
- self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
-
- if (turret_stdproc_init("machinegun_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/machinegun.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fire routine
- self.turret_firefunc = turret_machinegun_attack;
-
-}
-
-
-
-/*
-* machinegun turret. does what you'd expect
-*/
-
-/*QUAKED turret_machinegun (0 .5 .8) ?
-*/
-void spawnfunc_turret_machinegun()
-{
- precache_model ("models/turrets/machinegun.md3");
- precache_model ("models/turrets/base.md3");
- precache_sound ("weapons/uzi_fire.wav");
-
- self.think = turret_machinegun_std_init;
- self.nextthink = time + 0.5;
-}
-
+void spawnfunc_turret_machinegun();
+void turret_machinegun_std_init();
+void turret_machinegun_attack();
+
+//.float bulletcounter;
+void turret_machinegun_attack()
+{
+
+ entity flash;
+
+ sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
+ fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, cvar("g_balance_uzi_bulletconstant"));
+
+ //w_deathtypestring = "had an alergic reaction due to 10 kilos of led";
+ te_smallflash(self.tur_shotorg);
+ // trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
+
+ // muzzle flash for 3rd person view
+ flash = spawn();
+ //setorigin(flash, '43 1 8');
+ setmodel(flash, "models/uziflash.md3"); // precision set below
+ setattachment(flash, self.tur_head, "tag_fire");
+ flash.think = W_Uzi_Flash_Go;
+ flash.nextthink = time + 0.02;
+ flash.frame = 2;
+ flash.angles_z = flash.v_angle_z + random() * 180;
+ flash.alpha = 1;
+ flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+}
+
+
+void turret_machinegun_std_init()
+{
+ if (self.netname == "") self.netname = "Machinegun Turret";
+
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+ self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL;// | TFL_TURRCAPS_MISSILEKILL;
+ self.aim_flags = TFL_AIM_LEAD;
+
+ if(cvar("g_antilag_bullets"))
+ self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
+ else
+ self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
+
+ if (turret_stdproc_init("machinegun_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/machinegun.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fire routine
+ self.turret_firefunc = turret_machinegun_attack;
+
+}
+
+
+
+/*
+* machinegun turret. does what you'd expect
+*/
+
+/*QUAKED turret_machinegun (0 .5 .8) ?
+*/
+void spawnfunc_turret_machinegun()
+{
+ precache_model ("models/turrets/machinegun.md3");
+ precache_model ("models/turrets/base.md3");
+ precache_sound ("weapons/uzi_fire.wav");
+
+ self.think = turret_machinegun_std_init;
+ self.nextthink = time + 0.5;
+}
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_machinegun.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_mlrs.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_mlrs.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_mlrs.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,142 +1,142 @@
-void spawnfunc_turret_mlrs();
-void turret_mlrs_dinit();
-void turret_mlrs_attack();
-void turret_mlrs_rocket_explode();
-void turret_mlrs_rocket_touch();
-
-void turret_mlrs_postthink()
-{
-
- // 0 = full, 6 = empty
- self.tur_head.frame = rint(6 - (self.ammo / self.shot_dmg));
-}
-
-void turret_mlrs_attack()
-{
- entity missile;
-
- turret_tag_fire_update();
-
- sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
-
- missile = spawn ();
- //setsize (missile, '0 0 0', '0 0 0'); // give it some size so it can be shot
- setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
- setorigin(missile, self.tur_shotorg);
- missile.classname = "mlrs_missile";
- missile.owner = self;
- missile.bot_dodge = TRUE;
- missile.bot_dodgerating = self.shot_dmg;
- missile.takedamage = DAMAGE_NO;
- missile.damageforcescale = 4;
- //missile.health = 25;
- missile.think = turret_mlrs_rocket_explode;
-
- missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
- //missile.nextthink = missile.nextthink + random() * self.shot_spread;
-
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- missile.angles = vectoangles(missile.velocity);
- missile.touch = turret_mlrs_rocket_touch;
- missile.flags = FL_PROJECTILE;
- missile.solid = SOLID_BBOX;
- missile.enemy = self.enemy;
-
- CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE); // no cull, fly sound
-
- te_explosion (missile.origin);
-
- //self.tur_head.frame = 7 - self.volly_counter;
-}
-
-void turret_mlrs_rocket_touch()
-{
- if( (other == self.owner) || (other == self.owner.tur_head) )
- return;
-
- PROJECTILE_TOUCH;
-
- turret_mlrs_rocket_explode();
-}
-
-void turret_mlrs_rocket_explode()
-{
- vector org2;
-
- if(self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = turret_mlrs_rocket_explode;
- self.nextthink = time;
- return;
- }
-
-
- sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
- org2 = findbetterlocation (self.origin, 16);
- pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
- //w_deathtypestring = "dident escape the rocket barrage";
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-#endif
-
- // Target dead, Tell turret.
- if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
- self.owner.enemy = world;
-
- remove (self);
-}
-
-void turret_mlrs_dinit()
-{
- if (self.netname == "") self.netname = "MLRS turret";
-
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
- self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_ZEASE | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_INFRONT;
-
- if (turret_stdproc_init("mlrs_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
-
- self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
- self.volly_counter = self.shot_volly;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/mlrs.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fire routine
- self.turret_firefunc = turret_mlrs_attack;
- self.turret_postthink = turret_mlrs_postthink;
-
-}
-
-/*QUAKED turret_mlrs (0 .5 .8) ?
-*/
-
-void spawnfunc_turret_mlrs()
-{
- //precache_model ( "models/turrets/rocket.md3");
- precache_model ("models/turrets/mlrs.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_mlrs_dinit;
- self.nextthink = time + 0.5;
-}
-
-
+void spawnfunc_turret_mlrs();
+void turret_mlrs_dinit();
+void turret_mlrs_attack();
+void turret_mlrs_rocket_explode();
+void turret_mlrs_rocket_touch();
+
+void turret_mlrs_postthink()
+{
+
+ // 0 = full, 6 = empty
+ self.tur_head.frame = rint(6 - (self.ammo / self.shot_dmg));
+}
+
+void turret_mlrs_attack()
+{
+ entity missile;
+
+ turret_tag_fire_update();
+
+ sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", VOL_BASE, ATTN_NORM);
+
+ missile = spawn ();
+ //setsize (missile, '0 0 0', '0 0 0'); // give it some size so it can be shot
+ setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+ setorigin(missile, self.tur_shotorg);
+ missile.classname = "mlrs_missile";
+ missile.owner = self;
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = self.shot_dmg;
+ missile.takedamage = DAMAGE_NO;
+ missile.damageforcescale = 4;
+ //missile.health = 25;
+ missile.think = turret_mlrs_rocket_explode;
+
+ missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
+ //missile.nextthink = missile.nextthink + random() * self.shot_spread;
+
+ missile.solid = SOLID_BBOX;
+ missile.movetype = MOVETYPE_FLYMISSILE;
+ missile.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ missile.angles = vectoangles(missile.velocity);
+ missile.touch = turret_mlrs_rocket_touch;
+ missile.flags = FL_PROJECTILE;
+ missile.solid = SOLID_BBOX;
+ missile.enemy = self.enemy;
+
+ CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE); // no cull, fly sound
+
+ te_explosion (missile.origin);
+
+ //self.tur_head.frame = 7 - self.volly_counter;
+}
+
+void turret_mlrs_rocket_touch()
+{
+ if( (other == self.owner) || (other == self.owner.tur_head) )
+ return;
+
+ PROJECTILE_TOUCH;
+
+ turret_mlrs_rocket_explode();
+}
+
+void turret_mlrs_rocket_explode()
+{
+ vector org2;
+
+ if(self.event_damage != SUB_Null)
+ {
+ self.event_damage = SUB_Null;
+ self.think = turret_mlrs_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+
+ sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+ org2 = findbetterlocation (self.origin, 16);
+ pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+ //w_deathtypestring = "dident escape the rocket barrage";
+#ifdef TURRET_DEBUG
+ float d;
+
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg * 0.5, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+#endif
+
+ // Target dead, Tell turret.
+ if ((self.enemy.deadflag != DEAD_NO) && (self.enemy == self.owner.enemy))
+ self.owner.enemy = world;
+
+ remove (self);
+}
+
+void turret_mlrs_dinit()
+{
+ if (self.netname == "") self.netname = "MLRS turret";
+
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
+ self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_ZEASE | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_INFRONT;
+
+ if (turret_stdproc_init("mlrs_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+
+ self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
+ self.volly_counter = self.shot_volly;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/mlrs.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fire routine
+ self.turret_firefunc = turret_mlrs_attack;
+ self.turret_postthink = turret_mlrs_postthink;
+
+}
+
+/*QUAKED turret_mlrs (0 .5 .8) ?
+*/
+
+void spawnfunc_turret_mlrs()
+{
+ //precache_model ( "models/turrets/rocket.md3");
+ precache_model ("models/turrets/mlrs.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_mlrs_dinit;
+ self.nextthink = time + 0.5;
+}
+
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_mlrs.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_phaser.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_phaser.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_phaser.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,149 +1,149 @@
-void spawnfunc_turret_phaser();
-void turret_phaser_dinit();
-void turret_phaser_attack();
-
-.float fireflag;
-
-float turret_phaser_firecheck()
-{
- if (self.fireflag != 0) return 0;
- return turret_stdproc_firecheck();
-}
-
-void turret_phaser_postthink()
-{
- if (self.tur_head.frame == 0)
- return;
-
- 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;
- }
- }
-}
-
-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, CHAN_PROJECTILE, "", VOL_BASE, ATTN_NORM);
- remove(self);
- return;
- }
-
- turret_do_updates(self.owner);
-
- if (time - self.shot_spread > 0)
- {
- self.shot_spread = time + 2;
- sound (self, CHAN_VOICE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM);
- }
-
-
- self.nextthink = time + self.ticrate;
-
- self.owner.attack_finished_single = time + frametime;
- entity oldself;
- oldself = self;
- self = self.owner;
- //w_deathtypestring = "was phased out of existence";
- 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);
- self = oldself;
- self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
-
-}
-
-void turret_phaser_attack()
-{
- entity beam;
-
- beam = spawn();
- beam.ticrate = 0.1; //cvar("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, CHAN_PROJECTILE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM);
- self.fireflag = 1;
-
- beam.attack_finished_single = self.attack_finished_single;
- self.attack_finished_single = time; // + cvar("sys_ticrate");
-
- setattachment(beam,self.tur_head,"tag_fire");
-
- soundat (self, trace_endpos, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-}
-
-void turret_phaser_dinit()
-{
- if (self.netname == "") self.netname = "Phaser Cannon";
-
- self.turrcaps_flags = TFL_TURRCAPS_SNIPER|TFL_TURRCAPS_HITSCAN|TFL_TURRCAPS_PLAYERKILL;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.aim_flags = TFL_AIM_ZEASE | TFL_AIM_LEAD;
-
- if (turret_stdproc_init("phaser_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/phaser.md3");
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- self.turret_firecheckfunc = turret_phaser_firecheck;
- self.turret_firefunc = turret_phaser_attack;
- self.turret_postthink = turret_phaser_postthink;
-
-}
-
-/*QUAKED turret_phaser(0 .5 .8) ?
-*/
-void spawnfunc_turret_phaser()
-{
- precache_sound ("turrets/phaser.wav");
- precache_model ("models/turrets/phaser.md3");
- precache_model ("models/turrets/phaser_beam.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_phaser_dinit;
- self.nextthink = time + 0.5;
-}
-
+void spawnfunc_turret_phaser();
+void turret_phaser_dinit();
+void turret_phaser_attack();
+
+.float fireflag;
+
+float turret_phaser_firecheck()
+{
+ if (self.fireflag != 0) return 0;
+ return turret_stdproc_firecheck();
+}
+
+void turret_phaser_postthink()
+{
+ if (self.tur_head.frame == 0)
+ return;
+
+ 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;
+ }
+ }
+}
+
+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, CHAN_PROJECTILE, "", VOL_BASE, ATTN_NORM);
+ remove(self);
+ return;
+ }
+
+ turret_do_updates(self.owner);
+
+ if (time - self.shot_spread > 0)
+ {
+ self.shot_spread = time + 2;
+ sound (self, CHAN_VOICE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM);
+ }
+
+
+ self.nextthink = time + self.ticrate;
+
+ self.owner.attack_finished_single = time + frametime;
+ entity oldself;
+ oldself = self;
+ self = self.owner;
+ //w_deathtypestring = "was phased out of existence";
+ 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);
+ self = oldself;
+ self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
+void turret_phaser_attack()
+{
+ entity beam;
+
+ beam = spawn();
+ beam.ticrate = 0.1; //cvar("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, CHAN_PROJECTILE, "turrets/phaser.wav", VOL_BASE, ATTN_NORM);
+ self.fireflag = 1;
+
+ beam.attack_finished_single = self.attack_finished_single;
+ self.attack_finished_single = time; // + cvar("sys_ticrate");
+
+ setattachment(beam,self.tur_head,"tag_fire");
+
+ soundat (self, trace_endpos, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+}
+
+void turret_phaser_dinit()
+{
+ if (self.netname == "") self.netname = "Phaser Cannon";
+
+ self.turrcaps_flags = TFL_TURRCAPS_SNIPER|TFL_TURRCAPS_HITSCAN|TFL_TURRCAPS_PLAYERKILL;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+ self.aim_flags = TFL_AIM_ZEASE | TFL_AIM_LEAD;
+
+ if (turret_stdproc_init("phaser_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/phaser.md3");
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ self.turret_firecheckfunc = turret_phaser_firecheck;
+ self.turret_firefunc = turret_phaser_attack;
+ self.turret_postthink = turret_phaser_postthink;
+
+}
+
+/*QUAKED turret_phaser(0 .5 .8) ?
+*/
+void spawnfunc_turret_phaser()
+{
+ precache_sound ("turrets/phaser.wav");
+ precache_model ("models/turrets/phaser.md3");
+ precache_model ("models/turrets/phaser_beam.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_phaser_dinit;
+ self.nextthink = time + 0.5;
+}
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_phaser.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_plasma.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_plasma.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_plasma.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,225 +1,225 @@
-void spawnfunc_turret_plasma();
-void spawnfunc_turret_plasma_dual();
-
-void turret_plasma_std_init();
-void turret_plasma_dual_init();
-
-void turret_plasma_attack();
-void turret_plasma_projectile_explode();
-
-void turret_plasma_postthink()
-{
- 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;
-}
-
-void turret_plasma_dual_postthink()
-{
- 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;
-}
-
-void turret_plasma_attack()
-{
- entity proj;
-
- sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
- pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '-1 -1 -1', '1 1 1');
- proj.classname = "plasmabomb";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_plasma_projectile_explode;
- proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- //proj.velocity = self.tur_shotdir_updated * self.shot_speed;
- proj.touch = turret_plasma_projectile_explode;
- proj.flags = FL_PROJECTILE;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
-
- if (self.tur_head.frame == 0)
- self.tur_head.frame = 1;
-}
-
-void turret_plasma_dual_attack()
-{
- entity proj;
-
- sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
- proj = spawn ();
- setorigin(proj, self.tur_shotorg);
- setsize(proj, '0 0 0', '0 0 0');
- proj.classname = "plasmabomb";
- proj.owner = self;
- proj.bot_dodge = TRUE;
- proj.bot_dodgerating = self.shot_dmg;
- proj.think = turret_plasma_projectile_explode;
- proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
- proj.movetype = MOVETYPE_FLYMISSILE;
- proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
- //proj.velocity = self.tur_shotdir_updated * self.shot_speed;
- proj.touch = turret_plasma_projectile_explode;
- proj.flags = FL_PROJECTILE;
- proj.enemy = self.enemy;
- proj.flags = FL_PROJECTILE | FL_NOTARGET;
-
- self.tur_head.frame += 1;
-
- CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
-}
-
-void turret_plasma_projectile_explode()
-{
- vector org2;
-
- org2 = findbetterlocation (self.origin, 8);
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, 79);
- WriteCoord (MSG_BROADCAST, org2_x);
- WriteCoord (MSG_BROADCAST, org2_y);
- WriteCoord (MSG_BROADCAST, org2_z);
- WriteCoord (MSG_BROADCAST, 0); // SeienAbunae: groan... Useless clutter
- WriteCoord (MSG_BROADCAST, 0);
- WriteCoord (MSG_BROADCAST, 0);
- WriteByte (MSG_BROADCAST, 155);
-
- self.event_damage = SUB_Null;
- //w_deathtypestring = "ate to much plasma";
-#ifdef TURRET_DEBUG
- float d;
-
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
- self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
- self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
- RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
-#endif
- sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
-
- remove (self);
-}
-
-void turret_plasma_std_init()
-{
- if (self.netname == "") self.netname = "Plasma Cannon";
-
- // What ammo to use
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
-
- // How to aim
- //self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_ZPREDICT | TFL_AIM_GROUND2;
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2;
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
-
- if (turret_stdproc_init("plasma_std",FALSE) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
-
- //self.firecheck_flags |= (TFL_FIRECHECK_AFF | TFL_FIRECHECK_VERIFIED);
- self.firecheck_flags |= TFL_FIRECHECK_AFF;
-
- //self.target_select_flags |= TFL_TARGETSELECT_FOV;
- //self.target_select_fov = 45;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/plasma.md3");
- // self.tur_head.alpha = -1;
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fireing routine
- self.turret_firefunc = turret_plasma_attack;
-
- // Custom per turret frame stuff. usualy animation.
- self.turret_postthink = turret_plasma_postthink;
- turret_do_updates(self);
-}
-
-
-void turret_plasma_dual_init()
-{
- if (self.netname == "") self.netname = "Dual Plasma Cannon";
-
- // What ammo to use
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
-
- // How to aim at targets
- self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2 ;
- self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
-
- if (turret_stdproc_init("plasma_dual",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.damage_flags |= TFL_DMG_HEADSHAKE;
- //self.firecheck_flags |= (TFL_FIRECHECK_AFF | TFL_FIRECHECK_VERIFIED);
- //self.firecheck_flags |= TFL_FIRECHECK_AFF;
-
- setmodel(self,"models/turrets/base.md3");
- setmodel(self.tur_head,"models/turrets/plasmad.md3");
-
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- // Our fireing routine
- self.turret_firefunc = turret_plasma_dual_attack;
-
- // Custom per turret frame stuff. usualy animation.
- self.turret_postthink = turret_plasma_dual_postthink;
-}
-
-
-/*
-* Basic moderate (std) or fast (dual) fireing, short-mid range energy cannon.
-* Not too mutch of a therat on its own, but can be rather dangerous in groups.
-* Regenerates ammo slowly, support with a fusionreactor(s) to do some real damage.
-*/
-
-/*QUAKED turret_plasma (0 .5 .8) ?
-*/
-void spawnfunc_turret_plasma()
-{
- g_turrets_common_precash();
- precache_model ("models/turrets/plasma.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_plasma_std_init;
- self.nextthink = time + 0.5;
-}
-
-/*QUAKED turret_plasma_dual (0 .5 .8) ?
-*/
-void spawnfunc_turret_plasma_dual()
-{
-
- precache_model ("models/turrets/plasmad.md3");
- precache_model ("models/turrets/base.md3");
-
- self.think = turret_plasma_dual_init;
- self.nextthink = time + 0.5;
-}
-
+void spawnfunc_turret_plasma();
+void spawnfunc_turret_plasma_dual();
+
+void turret_plasma_std_init();
+void turret_plasma_dual_init();
+
+void turret_plasma_attack();
+void turret_plasma_projectile_explode();
+
+void turret_plasma_postthink()
+{
+ 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;
+}
+
+void turret_plasma_dual_postthink()
+{
+ 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;
+}
+
+void turret_plasma_attack()
+{
+ entity proj;
+
+ sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
+ pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ setsize(proj, '-1 -1 -1', '1 1 1');
+ proj.classname = "plasmabomb";
+ proj.owner = self;
+ proj.bot_dodge = TRUE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_plasma_projectile_explode;
+ proj.nextthink = time + 9;
+ proj.solid = SOLID_BBOX;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ //proj.velocity = self.tur_shotdir_updated * self.shot_speed;
+ proj.touch = turret_plasma_projectile_explode;
+ proj.flags = FL_PROJECTILE;
+ proj.enemy = self.enemy;
+ proj.flags = FL_PROJECTILE | FL_NOTARGET;
+
+ CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
+
+ if (self.tur_head.frame == 0)
+ self.tur_head.frame = 1;
+}
+
+void turret_plasma_dual_attack()
+{
+ entity proj;
+
+ sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
+ proj = spawn ();
+ setorigin(proj, self.tur_shotorg);
+ setsize(proj, '0 0 0', '0 0 0');
+ proj.classname = "plasmabomb";
+ proj.owner = self;
+ proj.bot_dodge = TRUE;
+ proj.bot_dodgerating = self.shot_dmg;
+ proj.think = turret_plasma_projectile_explode;
+ proj.nextthink = time + 9;
+ proj.solid = SOLID_BBOX;
+ proj.movetype = MOVETYPE_FLYMISSILE;
+ proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
+ //proj.velocity = self.tur_shotdir_updated * self.shot_speed;
+ proj.touch = turret_plasma_projectile_explode;
+ proj.flags = FL_PROJECTILE;
+ proj.enemy = self.enemy;
+ proj.flags = FL_PROJECTILE | FL_NOTARGET;
+
+ self.tur_head.frame += 1;
+
+ CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
+}
+
+void turret_plasma_projectile_explode()
+{
+ vector org2;
+
+ org2 = findbetterlocation (self.origin, 8);
+ WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte (MSG_BROADCAST, 79);
+ WriteCoord (MSG_BROADCAST, org2_x);
+ WriteCoord (MSG_BROADCAST, org2_y);
+ WriteCoord (MSG_BROADCAST, org2_z);
+ WriteCoord (MSG_BROADCAST, 0); // SeienAbunae: groan... Useless clutter
+ WriteCoord (MSG_BROADCAST, 0);
+ WriteCoord (MSG_BROADCAST, 0);
+ WriteByte (MSG_BROADCAST, 155);
+
+ self.event_damage = SUB_Null;
+ //w_deathtypestring = "ate to much plasma";
+#ifdef TURRET_DEBUG
+ float d;
+
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+ self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; //self.owner.shot_dmg;
+ self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+ RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, world, self.owner.shot_force, DEATH_TURRET, world);
+#endif
+ sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
+
+ remove (self);
+}
+
+void turret_plasma_std_init()
+{
+ if (self.netname == "") self.netname = "Plasma Cannon";
+
+ // What ammo to use
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+
+ // How to aim
+ //self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_ZPREDICT | TFL_AIM_GROUND2;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2;
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
+
+ if (turret_stdproc_init("plasma_std",FALSE) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+
+ //self.firecheck_flags |= (TFL_FIRECHECK_AFF | TFL_FIRECHECK_VERIFIED);
+ self.firecheck_flags |= TFL_FIRECHECK_AFF;
+
+ //self.target_select_flags |= TFL_TARGETSELECT_FOV;
+ //self.target_select_fov = 45;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/plasma.md3");
+ // self.tur_head.alpha = -1;
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fireing routine
+ self.turret_firefunc = turret_plasma_attack;
+
+ // Custom per turret frame stuff. usualy animation.
+ self.turret_postthink = turret_plasma_postthink;
+ turret_do_updates(self);
+}
+
+
+void turret_plasma_dual_init()
+{
+ if (self.netname == "") self.netname = "Dual Plasma Cannon";
+
+ // What ammo to use
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+
+ // How to aim at targets
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_GROUND2 ;
+ self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
+
+ if (turret_stdproc_init("plasma_dual",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.damage_flags |= TFL_DMG_HEADSHAKE;
+ //self.firecheck_flags |= (TFL_FIRECHECK_AFF | TFL_FIRECHECK_VERIFIED);
+ //self.firecheck_flags |= TFL_FIRECHECK_AFF;
+
+ setmodel(self,"models/turrets/base.md3");
+ setmodel(self.tur_head,"models/turrets/plasmad.md3");
+
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ // Our fireing routine
+ self.turret_firefunc = turret_plasma_dual_attack;
+
+ // Custom per turret frame stuff. usualy animation.
+ self.turret_postthink = turret_plasma_dual_postthink;
+}
+
+
+/*
+* Basic moderate (std) or fast (dual) fireing, short-mid range energy cannon.
+* Not too mutch of a therat on its own, but can be rather dangerous in groups.
+* Regenerates ammo slowly, support with a fusionreactor(s) to do some real damage.
+*/
+
+/*QUAKED turret_plasma (0 .5 .8) ?
+*/
+void spawnfunc_turret_plasma()
+{
+ g_turrets_common_precash();
+ precache_model ("models/turrets/plasma.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_plasma_std_init;
+ self.nextthink = time + 0.5;
+}
+
+/*QUAKED turret_plasma_dual (0 .5 .8) ?
+*/
+void spawnfunc_turret_plasma_dual()
+{
+
+ precache_model ("models/turrets/plasmad.md3");
+ precache_model ("models/turrets/base.md3");
+
+ self.think = turret_plasma_dual_init;
+ self.nextthink = time + 0.5;
+}
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_plasma.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_targettrigger.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_targettrigger.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_targettrigger.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,42 +1,42 @@
-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.turrcaps_flags & TFL_TURRCAPS_RECIVETARGETS)
- {
- 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 (!cvar("g_turrets"))
- {
- remove(self);
- return;
- }
-
- InitTrigger ();
-
- self.touch = turret_targettrigger_touch;
-}
+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.turrcaps_flags & TFL_TURRCAPS_RECIVETARGETS)
+ {
+ 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 (!cvar("g_turrets"))
+ {
+ remove(self);
+ return;
+ }
+
+ InitTrigger ();
+
+ self.touch = turret_targettrigger_touch;
+}
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_targettrigger.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_tessla.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_tessla.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_tessla.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,178 +1,178 @@
-void spawnfunc_turret_tesla();
-void turret_tesla_dinit();
-void turret_tesla_fire();
-
-.float toasted;
-entity toast(entity from, float range, float damage)
-{
- entity e;
- entity etarget;
- float d,dd;
-
- dd = range + 1;
-
- e = findradius(from.origin,range);
- while (e)
- {
- if ((e.toasted != 1) && (e != from))
- if (turret_validate_target(self,e,self.target_validate_flags) > 0)
- {
- traceline(from.origin,e.origin,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_smallflash(etarget.origin);
- te_csqc_lightningarc(from.origin,etarget.origin);
- Damage(etarget,self,self,damage,DEATH_TURRET,etarget.origin,'0 0 0');
- etarget.toasted = 1;
- }
-
- return etarget;
-}
-
-float turret_tesla_firecheck()
-{
- if not (turret_stdproc_firecheck())
- return 0;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.enemy = turret_select_target();
-
- if(self.enemy)
- return 1;
-
- return 0;
-
-}
-
-void turret_tesla_fire()
-{
- entity e,t;
- float d,r,i;
-
- //w_deathtypestring = "discoverd how a tesla coil works";
-
- 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_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- t = toast(e,r,d);
- remove(e);
-
- if (t == world) return;
-
- 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.5;
- r *= 0.85;
- t = toast(t,r,d);
- if (t == world) break;
- }
-
- e = findchainfloat(toasted, 1);
- while (e)
- {
- e.toasted = 0;
- e = e.chain;
- }
-}
-
-void turret_tesla_postthink()
-{
- if not (self.tur_active)
- {
- self.tur_head.avelocity = '0 0 0';
- return;
- }
-
- if(self.ammo < self.shot_dmg)
- {
- self.tur_head.avelocity = '0 9 0' * (self.ammo / self.shot_dmg);
- }
- else
- {
- self.tur_head.avelocity = '0 90 0' * (self.ammo / self.shot_dmg);
-
- if(self.attack_finished_single > time)
- return;
-
- 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));
- }
-}
-
-
-void turret_tesla_dinit()
-{
- if (self.netname == "") self.netname = "Tesla Coil";
-
- self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_OWM_AMMO;
- self.shoot_flags = TFL_SHOOT_CUSTOM;
- self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.aim_flags = TFL_AIM_NO;
- self.track_flags = TFL_TRACK_NO;
-
- if (turret_stdproc_init("tesla_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- setmodel(self,"models/turrets/tesla_base.md3");
- setmodel(self.tur_head,"models/turrets/tesla_head.md3");
-
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
- TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
-
- if (!turret_tag_setup())
- dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
-
- self.turret_firefunc = turret_tesla_fire;
- self.turret_postthink = turret_tesla_postthink;
- self.turret_firecheckfunc = turret_tesla_firecheck;
-}
-
-/*QUAKED turret_tesla (0 .5 .8) ?
-*/
-void spawnfunc_turret_tesla()
-{
- precache_model ("models/turrets/tesla_head.md3");
- precache_model ("models/turrets/tesla_base.md3");
-
-
- self.think = turret_tesla_dinit;
- self.nextthink = time + 0.5;
-}
-
+void spawnfunc_turret_tesla();
+void turret_tesla_dinit();
+void turret_tesla_fire();
+
+.float toasted;
+entity toast(entity from, float range, float damage)
+{
+ entity e;
+ entity etarget;
+ float d,dd;
+
+ dd = range + 1;
+
+ e = findradius(from.origin,range);
+ while (e)
+ {
+ if ((e.toasted != 1) && (e != from))
+ if (turret_validate_target(self,e,self.target_validate_flags) > 0)
+ {
+ traceline(from.origin,e.origin,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_smallflash(etarget.origin);
+ te_csqc_lightningarc(from.origin,etarget.origin);
+ Damage(etarget,self,self,damage,DEATH_TURRET,etarget.origin,'0 0 0');
+ etarget.toasted = 1;
+ }
+
+ return etarget;
+}
+
+float turret_tesla_firecheck()
+{
+ if not (turret_stdproc_firecheck())
+ return 0;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.enemy = turret_select_target();
+
+ if(self.enemy)
+ return 1;
+
+ return 0;
+
+}
+
+void turret_tesla_fire()
+{
+ entity e,t;
+ float d,r,i;
+
+ //w_deathtypestring = "discoverd how a tesla coil works";
+
+ 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_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ t = toast(e,r,d);
+ remove(e);
+
+ if (t == world) return;
+
+ 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.5;
+ r *= 0.85;
+ t = toast(t,r,d);
+ if (t == world) break;
+ }
+
+ e = findchainfloat(toasted, 1);
+ while (e)
+ {
+ e.toasted = 0;
+ e = e.chain;
+ }
+}
+
+void turret_tesla_postthink()
+{
+ if not (self.tur_active)
+ {
+ self.tur_head.avelocity = '0 0 0';
+ return;
+ }
+
+ if(self.ammo < self.shot_dmg)
+ {
+ self.tur_head.avelocity = '0 9 0' * (self.ammo / self.shot_dmg);
+ }
+ else
+ {
+ self.tur_head.avelocity = '0 90 0' * (self.ammo / self.shot_dmg);
+
+ if(self.attack_finished_single > time)
+ return;
+
+ 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));
+ }
+}
+
+
+void turret_tesla_dinit()
+{
+ if (self.netname == "") self.netname = "Tesla Coil";
+
+ self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MISSILEKILL;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ self.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_OWM_AMMO;
+ self.shoot_flags = TFL_SHOOT_CUSTOM;
+ self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+ self.aim_flags = TFL_AIM_NO;
+ self.track_flags = TFL_TRACK_NO;
+
+ if (turret_stdproc_init("tesla_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ setmodel(self,"models/turrets/tesla_base.md3");
+ setmodel(self.tur_head,"models/turrets/tesla_head.md3");
+
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+ TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
+
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ self.turret_firefunc = turret_tesla_fire;
+ self.turret_postthink = turret_tesla_postthink;
+ self.turret_firecheckfunc = turret_tesla_firecheck;
+}
+
+/*QUAKED turret_tesla (0 .5 .8) ?
+*/
+void spawnfunc_turret_tesla()
+{
+ precache_model ("models/turrets/tesla_head.md3");
+ precache_model ("models/turrets/tesla_base.md3");
+
+
+ self.think = turret_tesla_dinit;
+ self.nextthink = time + 0.5;
+}
+
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_tessla.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/tturrets/units/unit_walker.qc
===================================================================
--- trunk/data/qcsrc/server/tturrets/units/unit_walker.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/tturrets/units/unit_walker.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,1022 +1,1022 @@
-#define ANIM_NO 0
-#define ANIM_REVERSE 1
-#define ANIM_WALK 2
-#define ANIM_RUN 3
-#define ANIM_STRAFE_L 4
-#define ANIM_STRAFE_R 5
-#define ANIM_TURN 6
-#define ANIM_JUMP 7
-#define ANIM_LAND 8
-#define ANIM_PAIN 9
-#define ANIM_MEELE 10
-#define ANIM_SWIM 11
-#define ANIM_ROAM 12
-
-#define WVM_IDLE_UP 25
-#define WVM_IDLE 50
-
-#define WVM_PATH 1000
-#define WVM_ENEMY 2000
-#define WVM_STOP 3000
-#define WVM_DODGE 4000
-#define WVM_PANIC 10000
-#define walker_verbs_move verbs_move
-
-#define WVA_MINIGUN 100
-#define WVA_ROCKET 500
-#define WVA_MEELE 1000
-#define walker_verbs_attack verbs_attack
-
-#define WVI_IDLE 1
-#define WVI_ROAM 10
-#define walker_verbs_idle verbs_idle
-
-.float animflag;
-.entity wkr_spawn;
-
-#define WALKER_MIN '-70 -70 5'
-#define WALKER_MAX '70 70 70'
-
-#define WALKER_PATH(s,e) pathlib_astar(s,e)
-
-float walker_firecheck()
-{
- if (self.animflag == ANIM_MEELE)
- return 0;
-
- return turret_stdproc_firecheck();
-}
-
-void walker_meele_do_dmg()
-{
- vector where;
- entity e;
- makevectors(self.angles);
- where = self.origin + v_forward * 128;
-
- //w_deathtypestring = "tried to hug the cute spider thingy.";
- e = findradius(where,64);
- while (e)
- {
- if (turret_validate_target(self,e,self.target_validate_flags))
- if (e != self && e.owner != self)
- Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg"),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") );
-
- e = e.chain;
- }
-}
-
-void walker_animate()
-{
- vector real_angle;
- float vz;
-
- real_angle = vectoangles(self.steerto) - self.angles;
- vz = self.velocity_z;
-
- if (self.tur_head.frame != 0)
- self.tur_head.frame = self.tur_head.frame +1;
-
- if (self.tur_head.frame > 12)
- self.tur_head.frame = 0;
-
- switch (self.animflag)
- {
-
- case ANIM_NO:
- if (self.frame != 0)
- self.frame = 0;
-
- movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
-
- break;
-
- case ANIM_REVERSE:
- if ((self.frame < 5) || (self.frame > 25))
- self.frame = 25;
-
- self.frame = self.frame -1;
- movelib_move_simple(v_forward * -1 ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
-
- if (self.frame < 5)
- self.frame = 25;
-
- break;
-
- case ANIM_TURN:
-
- if ((self.frame < 30) || (self.frame > 55))
- self.frame = 30;
-
- self.frame = self.frame + 1;
-
- self.angles_y += bound(-15,shortangle_f(real_angle_y,self.angles_y),15);
-
- movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
-
- if (self.frame > 55)
- self.frame = 35;
-
- break;
-
- case ANIM_WALK:
- if ((self.frame < 5) || (self.frame > 25))
- self.frame = 5;
-
- self.frame = self.frame +1;
- self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
- movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
-
- if (self.frame > 25)
- self.frame = 5;
-
- break;
-
- case ANIM_ROAM:
- if ((self.frame < 5) || (self.frame > 25))
- self.frame = 5;
-
- self.frame = self.frame +1;
-
- self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
-
- movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_roam"),0.5);
-
- if (self.frame > 25)
- self.frame = 5;
-
- break;
-
- case ANIM_SWIM:
- if ((self.frame < 142) || (self.frame > 151))
- self.frame = 142;
-
- self.frame = self.frame +1;
-
- self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
- self.angles_x += bound(-10,shortangle_f(real_angle_x,self.angles_x),10);
-
- movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_swim"),0.3);
- vz = self.velocity_z + sin(time * 4) * 8;
-
- if (self.frame > 151)
- self.frame = 146;
-
- break;
-
- case ANIM_RUN:
-
- if ((self.frame < 5) || (self.frame > 25))
- self.frame = 5;
-
- self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
- movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_run"),0.6);
-
- if (self.frame > 25)
- self.frame = 5;
-
- break;
-
- case ANIM_STRAFE_L:
- if ((self.frame < 30) || (self.frame > 55))
- self.frame = 30;
-
- self.frame = self.frame + 1;
- self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
- movelib_move_simple(v_right * -1, cvar("g_turrets_unit_walker_speed_walk"),0.8);
-
- if (self.frame > 55)
- self.frame = 35;
- break;
-
- case ANIM_STRAFE_R:
- if ((self.frame < 60) || (self.frame > 65))
- self.frame = 60;
-
- self.frame = self.frame + 1;
- self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
- movelib_move_simple(v_right, cvar("g_turrets_unit_walker_speed_walk"),0.8);
-
- if (self.frame > 85)
- self.frame = 65;
-
- break;
-
- case ANIM_JUMP:
- if ((self.frame < 95) || (self.frame > 100))
- self.frame = 95;
-
- self.velocity += '0 0 1' * cvar("g_turrets_unit_walker_speed_jump");
-
- if (self.frame > 100)
- self.frame = self.frame + 1;
-
- break;
-
- case ANIM_LAND:
- if ((self.frame < 100) || (self.frame > 107))
- self.frame = 100;
-
- self.frame = self.frame + 1;
-
- if (self.frame > 107)
- self.animflag = ANIM_NO;
-
- break;
-
- case ANIM_PAIN:
- if ((self.frame < 60) || (self.frame > 95))
- self.frame = 90;
-
- self.frame = self.frame + 1;
-
- if (self.frame > 95)
- self.animflag = ANIM_NO;
-
- break;
-
- case ANIM_MEELE:
- if ((self.frame < 123) || (self.frame > 140))
- self.frame = 123;
-
- movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
-
- self.frame = self.frame + 2;
-
- if (self.frame == 133)
- walker_meele_do_dmg();
-
- if (self.frame > 140)
- {
- self.animflag = ANIM_NO;
- self.frame = 0;
- }
- }
-
- self.velocity_z = vz;
-
- if (self.flags & FL_ONGROUND)
- movelib_groundalign4point(300,100,0.25);
-
-}
-
-
-void walker_rocket_explode()
-{
- vector org2;
-
- if (self.event_damage != SUB_Null)
- {
- self.event_damage = SUB_Null;
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
- org2 = findbetterlocation (self.origin, 16);
-
- pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
- //w_deathtypestring = "got blasted to oblivion";
- RadiusDamage (self, self.owner, cvar("g_turrets_unit_walker_std_rocket_dmg"), 0, cvar("g_turrets_unit_walker_std_rocket_radius"), world, cvar("g_turrets_unit_walker_std_rocket_force"), DEATH_TURRET, 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)
- walker_rocket_explode();
-}
-
-#define WALKER_ROCKET_MOVE movelib_move_simple(newdir,cvar("g_turrets_unit_walker_std_rocket_speed"),cvar("g_turrets_unit_walker_std_rocket_tunrate")); 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 < 256)
- self.tur_shotorg = '0 0 0';
-
-
- if (self.tur_health < time)
- {
- self.think = walker_rocket_explode;
- self.nextthink = time;
- return;
- }
-
- if (self.shot_dmg != 1337)
- if (random() < 0.01)
- {
- walker_rocket_loop();
- return;
- }
-
- m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
-
- // 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;
- }
-
- 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.tur_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 128 )
- {
- 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.tur_health < time)
- {
- self.think = walker_rocket_explode;
- return;
- }
-
- if (vlen(self.origin - self.tur_shotorg) < 128 )
- {
- 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 400';
- self.think = walker_rocket_loop2;
- self.shot_dmg = 1337;
-}
-
-void walker_fire_rocket(vector org)
-{
-
- entity rocket;
-
-
- self.angles_x *= -1;
- makevectors(self.angles);
- self.angles_x *= -1;
-
- te_explosion (org);
-
- rocket = spawn ();
- setorigin(rocket, org);
-
- sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_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;// + 0.25;
- rocket.movetype = MOVETYPE_FLY;
- rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * cvar("g_turrets_unit_walker_std_rocket_speed");
- rocket.angles = vectoangles(rocket.velocity);
- rocket.touch = walker_rocket_explode;
- rocket.flags = FL_PROJECTILE;
- rocket.solid = SOLID_BBOX;
- rocket.tur_health = time + 9;
-
- CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
-}
-
-void rv_think()
-{
- float f;
- vector org;
- entity oldself;
-
- if (self.owner.deadflag != DEAD_NO)
- {
- remove(self);
- return;
- }
-
- self.cnt = self.cnt -1;
-
- if (self.cnt < 0)
- {
- remove(self);
- return;
- }
-
- if (self.cnt > 1)
- f = gettagindex(self.owner,"tag_rocket01");
- else
- f = gettagindex(self.owner,"tag_rocket02");
-
- org = gettaginfo(self.owner,f);
-
- self.nextthink = time + 0.2;
- oldself = self;
- self = self.owner;
- walker_fire_rocket(org);
- self = oldself;
-}
-
-float walker_moveverb_path(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- if (self.pathcurrent)
- return verb.verb_static_value;
-
- return VS_CALL_NO;
-
- case VCM_DO:
- // Do we have a path?
- if not(self.pathcurrent)
- {
- return VS_CALL_NO;
- }
- else
- {
- // 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;
- }
-
-
- if (self.pathcurrent)
- {
- switch (self.waterlevel)
- {
- case 0:
- self.animflag = ANIM_WALK;
- case 1:
- case 2:
- if (self.animflag == ANIM_WALK)
- self.animflag = ANIM_WALK;
- else
- self.animflag = ANIM_SWIM;
- break;
- case 3:
- self.animflag = ANIM_SWIM;
- }
-
- self.moveto = self.pathcurrent.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
-
- return VS_CALL_YES_DOING;
- }
- else
- return VS_CALL_YES_DONE;
-
- case VCM_REMOVE:
-
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-
- self.pathcurrent = world;
-
- return VS_CALL_YES_DONE;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_moveverb_enemy(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.enemy)
- if (self.spawnflags & TSF_NO_PATHBREAK)
- if (self.pathcurrent)
- return VS_CALL_NO;
-
- if (self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- if (self.enemy == world)
- return VS_CALL_NO;
-
- //if (tracewalk(self.enemy, self.origin, self.mins, self.maxs, self.enemy.origin, MOVE_NORMAL))
- return verb.verb_static_value;
-
- //return VS_CALL_NO;
-
- case VCM_DO:
- switch (self.waterlevel)
- {
- case 0:
- if (self.tur_dist_enemy > 500)
- self.animflag = ANIM_RUN;
- else
- self.animflag = ANIM_WALK;
- case 1:
- case 2:
- if (self.animflag != ANIM_SWIM)
- self.animflag = ANIM_WALK;
- else
- self.animflag = ANIM_SWIM;
- break;
- case 3:
- self.animflag = ANIM_SWIM;
- }
-
- self.moveto = self.enemy.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_moveverb_idle_pause(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- self.moveto = self.origin;
- self.steerto = v_forward;
- self.animflag = ANIM_NO;
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_moveverb_idle_roam(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
- if(verb.wait < time)
- {
- trace_fraction = 0;
- while(trace_fraction != 1.0)
- {
- self.moveto = self.origin + (v_forward * 256);
- self.moveto += v_right * (random() * 256);
- self.moveto -= v_right * (random() * 256);
-
- tracebox(self.origin+'0 0 64',self.mins,self.maxs,self.moveto + '0 0 64',MOVE_NORMAL,self);
- }
- verb.wait = time + 10;
- }
- else
- {
- if(verb.wait - time < 9)
- if(vlen(self.moveto - self.origin) < 32)
- {
- verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause, WVM_IDLE + WVM_IDLE_UP, random() * (verb.wait - time), self);
- self.animflag = ANIM_NO;
- return VS_CALL_REMOVE;
- }
- }
-
- self.steerto = steerlib_attract(self.moveto,256);
- te_lightning1(self,self.origin + '0 0 64',self.moveto + '0 0 64');
-
-
-
- switch (self.waterlevel)
- {
- case 0:
- self.animflag = ANIM_ROAM;
- case 1:
- case 2:
- if (self.animflag != ANIM_SWIM)
- self.animflag = ANIM_ROAM;
-
- break;
- case 3:
- self.animflag = ANIM_SWIM;
- }
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_moveverb_idle(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- if (self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- //if (random() < 0.5)
- verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause, WVM_IDLE + WVM_IDLE_UP, random() * 5, self);
- //else
- // verbstack_push(self.walker_verbs_move, walker_moveverb_idle_roam, WVM_IDLE + WVM_IDLE_UP, random() * 15);
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_attackverb_meele(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
-
- vector wish_angle;
-
- if (cvar("g_turrets_nofire"))
- return VS_CALL_NO;
-
- if (self.animflag == ANIM_SWIM || self.animflag == ANIM_MEELE)
- return VS_CALL_NO;
-
- if (!self.enemy)
- return VS_CALL_NO;
-
- wish_angle = angleofs(self,self.enemy);
-
- if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
- if (fabs(wish_angle_y) < 15)
- return verb.verb_static_value;
-
- return VS_CALL_NO;
-
- case VCM_DO:
-
- self.moveto = self.enemy.origin;
- self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
- self.animflag = ANIM_MEELE;
-
- return VS_CALL_YES_DOING;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-float walker_attackverb_rockets(float eval)
-{
- switch (eval)
- {
- case VCM_EVAL:
- if (self.tur_head.attack_finished_single > time)
- return VS_CALL_NO;
-
- if not(self.enemy)
- return VS_CALL_NO;
-
- if (cvar("g_turrets_nofire"))
- return VS_CALL_NO;
-
- if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_rockets_range_min"))
- return VS_CALL_NO;
-
- if (self.tur_dist_enemy > cvar("g_turrets_unit_walker_std_rockets_range"))
- return VS_CALL_NO;
-
- return verb.verb_static_value;
-
- case VCM_DO:
-
- entity rv;
-
- rv = spawn();
- rv.think = rv_think;
- rv.nextthink = time;
- rv.cnt = 4;
- rv.owner = self;
-
- self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
-
- return VS_CALL_YES_DONE;
- }
-
- return VS_CALL_YES_DONE;
-}
-
-void walker_postthink()
-{
-
- self.angles_x *= -1;
- makevectors(self.angles);
- self.angles_x *= -1;
-
- verbstack_pop(self.walker_verbs_attack);
- verbstack_pop(self.walker_verbs_move);
-
- walker_animate();
-}
-
-void walker_attack()
-{
- entity flash;
-
- //w_deathtypestring = "was miniguned";
- sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, cvar("g_balance_uzi_bulletconstant"));
- if (self.uzi_bulletcounter == 2)
- {
-
- flash = spawn();
-
- setmodel(flash, "models/uziflash.md3");
- setattachment(flash, self.tur_head, "tag_fire");
-
- flash.scale = 3;
- flash.think = W_Uzi_Flash_Go;
- flash.nextthink = time + 0.02;
- flash.frame = 2;
- flash.angles_z = flash.v_angle_z + random() * 180;
- flash.alpha = 1;
- flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-
- self.uzi_bulletcounter = self.uzi_bulletcounter = 0;
- }
-
- self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
- self.tur_head.frame = self.tur_head.frame + 1;
-}
-
-
-void walker_respawnhook()
-{
- vector vtmp;
- entity e;
-
- self.origin = self.wkr_spawn.origin;
- //self.wkr_props.solid = SOLID_BBOX;
- //self.wkr_props.alpha = 1;
-
- self.angles = self.wkr_spawn.angles;
- vtmp = self.wkr_spawn.origin;
- vtmp_z += self.wkr_spawn.maxs_z;
- setorigin(self,vtmp);
-
- if (self.target != "")
- {
- e = find(world,targetname,self.target);
- if (!e)
- {
- dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
- self.target = "";
- }
-
- if (e.classname != "turret_checkpoint")
- dprint("Warning: not a turrret path\n");
- else
- {
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
- }
- }
-}
-void walker_diehook()
-{
- turret_trowgib2(self.origin,self.velocity + v_up * 200,'-0.6 -0.2 -02',self,time + random() * 1);
- turret_trowgib2(self.origin + '0 0 64',self.velocity + v_forward * 150 + v_up * 150,'-0.2 -0.2 -02',self.tur_head,time + random() * 2 + 3);
-
- if (self.pathcurrent)
- pathlib_deletepath(self.pathcurrent.owner);
-
- self.pathcurrent = world;
-
- if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
- {
- remove(self.wkr_spawn);
-
- verbstack_flush(self.walker_verbs_move);
- verbstack_flush(self.walker_verbs_attack);
- verbstack_flush(self.walker_verbs_idle);
-
- remove(self.walker_verbs_move);
- remove(self.walker_verbs_attack);
- remove(self.walker_verbs_idle);
- }
-
-}
-
-void turret_walker_dinit()
-{
-
- entity e;
-
- if (self.netname == "") self.netname = "Walker Turret";
- self.wkr_spawn = spawn();
-
- self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_HEADATTACHED;
- self.aim_flags = TFL_AIM_LEAD;
-
- if (cvar("g_antilag_bullets"))
- self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
- else
- self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
-
-
- self.turret_respawnhook = walker_respawnhook;
- self.turret_diehook = walker_diehook;
-
- self.ticrate = 0.05;
- if (turret_stdproc_init("walker_std",0) == 0)
- {
- remove(self);
- return;
- }
-
- self.walker_verbs_move = spawn();
- self.walker_verbs_attack = spawn();
- self.walker_verbs_idle = spawn();
-
- verbstack_push(self.walker_verbs_move, walker_moveverb_idle, WVM_IDLE, 0, self);
- verbstack_push(self.walker_verbs_move, walker_moveverb_enemy, WVM_ENEMY, 0, self);
- verbstack_push(self.walker_verbs_move, walker_moveverb_path, WVM_PATH, 0, self);
-
- verbstack_push(self.walker_verbs_attack, walker_attackverb_meele, WVA_MEELE, 0, self);
- verbstack_push(self.walker_verbs_attack, walker_attackverb_rockets, WVA_ROCKET, 0, self);
-
- self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
-
- self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
- self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-
- self.iscreature = TRUE;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.takedamage = DAMAGE_AIM;
-
- setmodel(self,"models/turrets/walker_body.md3");
- setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
- setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
-
- setattachment(self.tur_head,self,"tag_head");
-
- self.wkr_spawn.angles = self.angles;
- self.wkr_spawn.solid = SOLID_NOT;
-
- traceline(self.origin + '0 0 16', self.origin - '0 0 10000', MOVE_WORLDONLY, self);
- setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
- setorigin(self,self.wkr_spawn.origin);
-
- setsize(self,WALKER_MIN,WALKER_MAX);
-
- self.idle_aim = '0 0 0';
- self.turret_firecheckfunc = walker_firecheck;
- self.turret_firefunc = walker_attack;
- self.turret_postthink = walker_postthink;
-
- 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
- {
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
- self.pathgoal = e;
- }
- }
-}
-
-
-void spawnfunc_turret_walker()
-{
- g_turrets_common_precash();
-
- precache_model ("models/turrets/walker_head_minigun.md3");
- precache_model ("models/turrets/walker_body.md3");
- precache_model ("models/turrets/walker_props.md3");
- precache_model ("models/turrets/walker_spawn.md3");
- precache_model ( "models/turrets/rocket.md3");
- precache_sound ( "weapons/rocket_impact.wav" );
-
- self.think = turret_walker_dinit;
- self.nextthink = time + 0.5;
-}
+#define ANIM_NO 0
+#define ANIM_REVERSE 1
+#define ANIM_WALK 2
+#define ANIM_RUN 3
+#define ANIM_STRAFE_L 4
+#define ANIM_STRAFE_R 5
+#define ANIM_TURN 6
+#define ANIM_JUMP 7
+#define ANIM_LAND 8
+#define ANIM_PAIN 9
+#define ANIM_MEELE 10
+#define ANIM_SWIM 11
+#define ANIM_ROAM 12
+
+#define WVM_IDLE_UP 25
+#define WVM_IDLE 50
+
+#define WVM_PATH 1000
+#define WVM_ENEMY 2000
+#define WVM_STOP 3000
+#define WVM_DODGE 4000
+#define WVM_PANIC 10000
+#define walker_verbs_move verbs_move
+
+#define WVA_MINIGUN 100
+#define WVA_ROCKET 500
+#define WVA_MEELE 1000
+#define walker_verbs_attack verbs_attack
+
+#define WVI_IDLE 1
+#define WVI_ROAM 10
+#define walker_verbs_idle verbs_idle
+
+.float animflag;
+.entity wkr_spawn;
+
+#define WALKER_MIN '-70 -70 5'
+#define WALKER_MAX '70 70 70'
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{
+ if (self.animflag == ANIM_MEELE)
+ return 0;
+
+ return turret_stdproc_firecheck();
+}
+
+void walker_meele_do_dmg()
+{
+ vector where;
+ entity e;
+ makevectors(self.angles);
+ where = self.origin + v_forward * 128;
+
+ //w_deathtypestring = "tried to hug the cute spider thingy.";
+ e = findradius(where,64);
+ while (e)
+ {
+ if (turret_validate_target(self,e,self.target_validate_flags))
+ if (e != self && e.owner != self)
+ Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg"),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") );
+
+ e = e.chain;
+ }
+}
+
+void walker_animate()
+{
+ vector real_angle;
+ float vz;
+
+ real_angle = vectoangles(self.steerto) - self.angles;
+ vz = self.velocity_z;
+
+ if (self.tur_head.frame != 0)
+ self.tur_head.frame = self.tur_head.frame +1;
+
+ if (self.tur_head.frame > 12)
+ self.tur_head.frame = 0;
+
+ switch (self.animflag)
+ {
+
+ case ANIM_NO:
+ if (self.frame != 0)
+ self.frame = 0;
+
+ movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
+
+ break;
+
+ case ANIM_REVERSE:
+ if ((self.frame < 5) || (self.frame > 25))
+ self.frame = 25;
+
+ self.frame = self.frame -1;
+ movelib_move_simple(v_forward * -1 ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
+
+ if (self.frame < 5)
+ self.frame = 25;
+
+ break;
+
+ case ANIM_TURN:
+
+ if ((self.frame < 30) || (self.frame > 55))
+ self.frame = 30;
+
+ self.frame = self.frame + 1;
+
+ self.angles_y += bound(-15,shortangle_f(real_angle_y,self.angles_y),15);
+
+ movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
+
+ if (self.frame > 55)
+ self.frame = 35;
+
+ break;
+
+ case ANIM_WALK:
+ if ((self.frame < 5) || (self.frame > 25))
+ self.frame = 5;
+
+ self.frame = self.frame +1;
+ self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
+ movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
+
+ if (self.frame > 25)
+ self.frame = 5;
+
+ break;
+
+ case ANIM_ROAM:
+ if ((self.frame < 5) || (self.frame > 25))
+ self.frame = 5;
+
+ self.frame = self.frame +1;
+
+ self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
+
+ movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_roam"),0.5);
+
+ if (self.frame > 25)
+ self.frame = 5;
+
+ break;
+
+ case ANIM_SWIM:
+ if ((self.frame < 142) || (self.frame > 151))
+ self.frame = 142;
+
+ self.frame = self.frame +1;
+
+ self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
+ self.angles_x += bound(-10,shortangle_f(real_angle_x,self.angles_x),10);
+
+ movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_swim"),0.3);
+ vz = self.velocity_z + sin(time * 4) * 8;
+
+ if (self.frame > 151)
+ self.frame = 146;
+
+ break;
+
+ case ANIM_RUN:
+
+ if ((self.frame < 5) || (self.frame > 25))
+ self.frame = 5;
+
+ self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
+ movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_run"),0.6);
+
+ if (self.frame > 25)
+ self.frame = 5;
+
+ break;
+
+ case ANIM_STRAFE_L:
+ if ((self.frame < 30) || (self.frame > 55))
+ self.frame = 30;
+
+ self.frame = self.frame + 1;
+ self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
+ movelib_move_simple(v_right * -1, cvar("g_turrets_unit_walker_speed_walk"),0.8);
+
+ if (self.frame > 55)
+ self.frame = 35;
+ break;
+
+ case ANIM_STRAFE_R:
+ if ((self.frame < 60) || (self.frame > 65))
+ self.frame = 60;
+
+ self.frame = self.frame + 1;
+ self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
+ movelib_move_simple(v_right, cvar("g_turrets_unit_walker_speed_walk"),0.8);
+
+ if (self.frame > 85)
+ self.frame = 65;
+
+ break;
+
+ case ANIM_JUMP:
+ if ((self.frame < 95) || (self.frame > 100))
+ self.frame = 95;
+
+ self.velocity += '0 0 1' * cvar("g_turrets_unit_walker_speed_jump");
+
+ if (self.frame > 100)
+ self.frame = self.frame + 1;
+
+ break;
+
+ case ANIM_LAND:
+ if ((self.frame < 100) || (self.frame > 107))
+ self.frame = 100;
+
+ self.frame = self.frame + 1;
+
+ if (self.frame > 107)
+ self.animflag = ANIM_NO;
+
+ break;
+
+ case ANIM_PAIN:
+ if ((self.frame < 60) || (self.frame > 95))
+ self.frame = 90;
+
+ self.frame = self.frame + 1;
+
+ if (self.frame > 95)
+ self.animflag = ANIM_NO;
+
+ break;
+
+ case ANIM_MEELE:
+ if ((self.frame < 123) || (self.frame > 140))
+ self.frame = 123;
+
+ movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
+
+ self.frame = self.frame + 2;
+
+ if (self.frame == 133)
+ walker_meele_do_dmg();
+
+ if (self.frame > 140)
+ {
+ self.animflag = ANIM_NO;
+ self.frame = 0;
+ }
+ }
+
+ self.velocity_z = vz;
+
+ if (self.flags & FL_ONGROUND)
+ movelib_groundalign4point(300,100,0.25);
+
+}
+
+
+void walker_rocket_explode()
+{
+ vector org2;
+
+ if (self.event_damage != SUB_Null)
+ {
+ self.event_damage = SUB_Null;
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+ org2 = findbetterlocation (self.origin, 16);
+
+ pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+ //w_deathtypestring = "got blasted to oblivion";
+ RadiusDamage (self, self.owner, cvar("g_turrets_unit_walker_std_rocket_dmg"), 0, cvar("g_turrets_unit_walker_std_rocket_radius"), world, cvar("g_turrets_unit_walker_std_rocket_force"), DEATH_TURRET, 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)
+ walker_rocket_explode();
+}
+
+#define WALKER_ROCKET_MOVE movelib_move_simple(newdir,cvar("g_turrets_unit_walker_std_rocket_speed"),cvar("g_turrets_unit_walker_std_rocket_tunrate")); 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 < 256)
+ self.tur_shotorg = '0 0 0';
+
+
+ if (self.tur_health < time)
+ {
+ self.think = walker_rocket_explode;
+ self.nextthink = time;
+ return;
+ }
+
+ if (self.shot_dmg != 1337)
+ if (random() < 0.01)
+ {
+ walker_rocket_loop();
+ return;
+ }
+
+ m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
+
+ // 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;
+ }
+
+ 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.tur_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 128 )
+ {
+ 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.tur_health < time)
+ {
+ self.think = walker_rocket_explode;
+ return;
+ }
+
+ if (vlen(self.origin - self.tur_shotorg) < 128 )
+ {
+ 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 400';
+ self.think = walker_rocket_loop2;
+ self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{
+
+ entity rocket;
+
+
+ self.angles_x *= -1;
+ makevectors(self.angles);
+ self.angles_x *= -1;
+
+ te_explosion (org);
+
+ rocket = spawn ();
+ setorigin(rocket, org);
+
+ sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_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;// + 0.25;
+ rocket.movetype = MOVETYPE_FLY;
+ rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * cvar("g_turrets_unit_walker_std_rocket_speed");
+ rocket.angles = vectoangles(rocket.velocity);
+ rocket.touch = walker_rocket_explode;
+ rocket.flags = FL_PROJECTILE;
+ rocket.solid = SOLID_BBOX;
+ rocket.tur_health = time + 9;
+
+ CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
+}
+
+void rv_think()
+{
+ float f;
+ vector org;
+ entity oldself;
+
+ if (self.owner.deadflag != DEAD_NO)
+ {
+ remove(self);
+ return;
+ }
+
+ self.cnt = self.cnt -1;
+
+ if (self.cnt < 0)
+ {
+ remove(self);
+ return;
+ }
+
+ if (self.cnt > 1)
+ f = gettagindex(self.owner,"tag_rocket01");
+ else
+ f = gettagindex(self.owner,"tag_rocket02");
+
+ org = gettaginfo(self.owner,f);
+
+ self.nextthink = time + 0.2;
+ oldself = self;
+ self = self.owner;
+ walker_fire_rocket(org);
+ self = oldself;
+}
+
+float walker_moveverb_path(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ if (self.pathcurrent)
+ return verb.verb_static_value;
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+ // Do we have a path?
+ if not(self.pathcurrent)
+ {
+ return VS_CALL_NO;
+ }
+ else
+ {
+ // 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;
+ }
+
+
+ if (self.pathcurrent)
+ {
+ switch (self.waterlevel)
+ {
+ case 0:
+ self.animflag = ANIM_WALK;
+ case 1:
+ case 2:
+ if (self.animflag == ANIM_WALK)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case 3:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = self.pathcurrent.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+
+ return VS_CALL_YES_DOING;
+ }
+ else
+ return VS_CALL_YES_DONE;
+
+ case VCM_REMOVE:
+
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+
+ self.pathcurrent = world;
+
+ return VS_CALL_YES_DONE;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_moveverb_enemy(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.enemy)
+ if (self.spawnflags & TSF_NO_PATHBREAK)
+ if (self.pathcurrent)
+ return VS_CALL_NO;
+
+ if (self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ if (self.enemy == world)
+ return VS_CALL_NO;
+
+ //if (tracewalk(self.enemy, self.origin, self.mins, self.maxs, self.enemy.origin, MOVE_NORMAL))
+ return verb.verb_static_value;
+
+ //return VS_CALL_NO;
+
+ case VCM_DO:
+ switch (self.waterlevel)
+ {
+ case 0:
+ if (self.tur_dist_enemy > 500)
+ self.animflag = ANIM_RUN;
+ else
+ self.animflag = ANIM_WALK;
+ case 1:
+ case 2:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_WALK;
+ else
+ self.animflag = ANIM_SWIM;
+ break;
+ case 3:
+ self.animflag = ANIM_SWIM;
+ }
+
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_moveverb_idle_pause(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ self.moveto = self.origin;
+ self.steerto = v_forward;
+ self.animflag = ANIM_NO;
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_moveverb_idle_roam(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ if(verb.wait < time)
+ {
+ trace_fraction = 0;
+ while(trace_fraction != 1.0)
+ {
+ self.moveto = self.origin + (v_forward * 256);
+ self.moveto += v_right * (random() * 256);
+ self.moveto -= v_right * (random() * 256);
+
+ tracebox(self.origin+'0 0 64',self.mins,self.maxs,self.moveto + '0 0 64',MOVE_NORMAL,self);
+ }
+ verb.wait = time + 10;
+ }
+ else
+ {
+ if(verb.wait - time < 9)
+ if(vlen(self.moveto - self.origin) < 32)
+ {
+ verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause, WVM_IDLE + WVM_IDLE_UP, random() * (verb.wait - time), self);
+ self.animflag = ANIM_NO;
+ return VS_CALL_REMOVE;
+ }
+ }
+
+ self.steerto = steerlib_attract(self.moveto,256);
+ te_lightning1(self,self.origin + '0 0 64',self.moveto + '0 0 64');
+
+
+
+ switch (self.waterlevel)
+ {
+ case 0:
+ self.animflag = ANIM_ROAM;
+ case 1:
+ case 2:
+ if (self.animflag != ANIM_SWIM)
+ self.animflag = ANIM_ROAM;
+
+ break;
+ case 3:
+ self.animflag = ANIM_SWIM;
+ }
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_moveverb_idle(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if (self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ //if (random() < 0.5)
+ verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause, WVM_IDLE + WVM_IDLE_UP, random() * 5, self);
+ //else
+ // verbstack_push(self.walker_verbs_move, walker_moveverb_idle_roam, WVM_IDLE + WVM_IDLE_UP, random() * 15);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_attackverb_meele(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ vector wish_angle;
+
+ if (cvar("g_turrets_nofire"))
+ return VS_CALL_NO;
+
+ if (self.animflag == ANIM_SWIM || self.animflag == ANIM_MEELE)
+ return VS_CALL_NO;
+
+ if (!self.enemy)
+ return VS_CALL_NO;
+
+ wish_angle = angleofs(self,self.enemy);
+
+ if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
+ if (fabs(wish_angle_y) < 15)
+ return verb.verb_static_value;
+
+ return VS_CALL_NO;
+
+ case VCM_DO:
+
+ self.moveto = self.enemy.origin;
+ self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+ self.animflag = ANIM_MEELE;
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float walker_attackverb_rockets(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if (self.tur_head.attack_finished_single > time)
+ return VS_CALL_NO;
+
+ if not(self.enemy)
+ return VS_CALL_NO;
+
+ if (cvar("g_turrets_nofire"))
+ return VS_CALL_NO;
+
+ if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_rockets_range_min"))
+ return VS_CALL_NO;
+
+ if (self.tur_dist_enemy > cvar("g_turrets_unit_walker_std_rockets_range"))
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ entity rv;
+
+ rv = spawn();
+ rv.think = rv_think;
+ rv.nextthink = time;
+ rv.cnt = 4;
+ rv.owner = self;
+
+ self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
+
+ return VS_CALL_YES_DONE;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void walker_postthink()
+{
+
+ self.angles_x *= -1;
+ makevectors(self.angles);
+ self.angles_x *= -1;
+
+ verbstack_pop(self.walker_verbs_attack);
+ verbstack_pop(self.walker_verbs_move);
+
+ walker_animate();
+}
+
+void walker_attack()
+{
+ entity flash;
+
+ //w_deathtypestring = "was miniguned";
+ sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
+ fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, cvar("g_balance_uzi_bulletconstant"));
+ if (self.uzi_bulletcounter == 2)
+ {
+
+ flash = spawn();
+
+ setmodel(flash, "models/uziflash.md3");
+ setattachment(flash, self.tur_head, "tag_fire");
+
+ flash.scale = 3;
+ flash.think = W_Uzi_Flash_Go;
+ flash.nextthink = time + 0.02;
+ flash.frame = 2;
+ flash.angles_z = flash.v_angle_z + random() * 180;
+ flash.alpha = 1;
+ flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+
+ self.uzi_bulletcounter = self.uzi_bulletcounter = 0;
+ }
+
+ self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
+ self.tur_head.frame = self.tur_head.frame + 1;
+}
+
+
+void walker_respawnhook()
+{
+ vector vtmp;
+ entity e;
+
+ self.origin = self.wkr_spawn.origin;
+ //self.wkr_props.solid = SOLID_BBOX;
+ //self.wkr_props.alpha = 1;
+
+ self.angles = self.wkr_spawn.angles;
+ vtmp = self.wkr_spawn.origin;
+ vtmp_z += self.wkr_spawn.maxs_z;
+ setorigin(self,vtmp);
+
+ if (self.target != "")
+ {
+ e = find(world,targetname,self.target);
+ if (!e)
+ {
+ dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
+ self.target = "";
+ }
+
+ if (e.classname != "turret_checkpoint")
+ dprint("Warning: not a turrret path\n");
+ else
+ {
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+ }
+ }
+}
+void walker_diehook()
+{
+ turret_trowgib2(self.origin,self.velocity + v_up * 200,'-0.6 -0.2 -02',self,time + random() * 1);
+ turret_trowgib2(self.origin + '0 0 64',self.velocity + v_forward * 150 + v_up * 150,'-0.2 -0.2 -02',self.tur_head,time + random() * 2 + 3);
+
+ if (self.pathcurrent)
+ pathlib_deletepath(self.pathcurrent.owner);
+
+ self.pathcurrent = world;
+
+ if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
+ {
+ remove(self.wkr_spawn);
+
+ verbstack_flush(self.walker_verbs_move);
+ verbstack_flush(self.walker_verbs_attack);
+ verbstack_flush(self.walker_verbs_idle);
+
+ remove(self.walker_verbs_move);
+ remove(self.walker_verbs_attack);
+ remove(self.walker_verbs_idle);
+ }
+
+}
+
+void turret_walker_dinit()
+{
+
+ entity e;
+
+ if (self.netname == "") self.netname = "Walker Turret";
+ self.wkr_spawn = spawn();
+
+ self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
+ self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_HEADATTACHED;
+ self.aim_flags = TFL_AIM_LEAD;
+
+ if (cvar("g_antilag_bullets"))
+ self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
+ else
+ self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
+
+
+ self.turret_respawnhook = walker_respawnhook;
+ self.turret_diehook = walker_diehook;
+
+ self.ticrate = 0.05;
+ if (turret_stdproc_init("walker_std",0) == 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.walker_verbs_move = spawn();
+ self.walker_verbs_attack = spawn();
+ self.walker_verbs_idle = spawn();
+
+ verbstack_push(self.walker_verbs_move, walker_moveverb_idle, WVM_IDLE, 0, self);
+ verbstack_push(self.walker_verbs_move, walker_moveverb_enemy, WVM_ENEMY, 0, self);
+ verbstack_push(self.walker_verbs_move, walker_moveverb_path, WVM_PATH, 0, self);
+
+ verbstack_push(self.walker_verbs_attack, walker_attackverb_meele, WVA_MEELE, 0, self);
+ verbstack_push(self.walker_verbs_attack, walker_attackverb_rockets, WVA_ROCKET, 0, self);
+
+ self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
+
+ self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+
+ self.iscreature = TRUE;
+ self.movetype = MOVETYPE_WALK;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+
+ setmodel(self,"models/turrets/walker_body.md3");
+ setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
+ setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
+
+ setattachment(self.tur_head,self,"tag_head");
+
+ self.wkr_spawn.angles = self.angles;
+ self.wkr_spawn.solid = SOLID_NOT;
+
+ traceline(self.origin + '0 0 16', self.origin - '0 0 10000', MOVE_WORLDONLY, self);
+ setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
+ setorigin(self,self.wkr_spawn.origin);
+
+ setsize(self,WALKER_MIN,WALKER_MAX);
+
+ self.idle_aim = '0 0 0';
+ self.turret_firecheckfunc = walker_firecheck;
+ self.turret_firefunc = walker_attack;
+ self.turret_postthink = walker_postthink;
+
+ 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
+ {
+ self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathgoal = e;
+ }
+ }
+}
+
+
+void spawnfunc_turret_walker()
+{
+ g_turrets_common_precash();
+
+ precache_model ("models/turrets/walker_head_minigun.md3");
+ precache_model ("models/turrets/walker_body.md3");
+ precache_model ("models/turrets/walker_props.md3");
+ precache_model ("models/turrets/walker_spawn.md3");
+ precache_model ( "models/turrets/rocket.md3");
+ precache_sound ( "weapons/rocket_impact.wav" );
+
+ self.think = turret_walker_dinit;
+ self.nextthink = time + 0.5;
+}
Property changes on: trunk/data/qcsrc/server/tturrets/units/unit_walker.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/vehicles/vehicles.qh
===================================================================
--- trunk/data/qcsrc/server/vehicles/vehicles.qh 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/vehicles/vehicles.qh 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,52 +1,52 @@
-//#define VEHICLES_ENABLED
-#ifdef VEHICLES_ENABLED
-
-#message "with tZork vehicles (experimental)"
-
-float SVC_SETVIEWPORT = 5; // Net.Protocol 0x05
-float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A
-float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80
-
-#define CCVAR(part) cvar(strcat(self.cvar_basename,part))
-//.string cvar_basename;
-
-.float vehicle_flags;
-#define VHF_HASSHIELD 2
-#define VHF_SHIELDREGEN 4
-#define VHF_HEALTHREGEN 8
-
-.float hud;
-.float rockets;
-.float rockets_reload;
-.entity gun1;
-.entity gun2;
-
-.float vehicle_health;
-.float vehicle_shield;
-.float vehicle_heat;
-
-.entity vehicle;
-.entity vehicle_viewport;
-.entity vehicle_hudmodel;
-
-.float anim_start;
-.float anim_end;
-
-.float dmg_time;
-
-float server_fps;
-
-#define VHEF_NORMAL 0
-#define VHEF_EJECT 1
-
-.void(float exit_flags) vehicle_exit;
-.void() vehicle_enter;
-.void() vehicle_die;
-.void() vehicle_spawn;
-.float(float message) vehicle_message;
-
-#include "vehicles.qc"
-#include "spiderbot.qc"
-#include "racer.qc"
-
-#endif
+//#define VEHICLES_ENABLED
+#ifdef VEHICLES_ENABLED
+
+#message "with tZork vehicles (experimental)"
+
+float SVC_SETVIEWPORT = 5; // Net.Protocol 0x05
+float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A
+float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80
+
+#define CCVAR(part) cvar(strcat(self.cvar_basename,part))
+//.string cvar_basename;
+
+.float vehicle_flags;
+#define VHF_HASSHIELD 2
+#define VHF_SHIELDREGEN 4
+#define VHF_HEALTHREGEN 8
+
+.float hud;
+.float rockets;
+.float rockets_reload;
+.entity gun1;
+.entity gun2;
+
+.float vehicle_health;
+.float vehicle_shield;
+.float vehicle_heat;
+
+.entity vehicle;
+.entity vehicle_viewport;
+.entity vehicle_hudmodel;
+
+.float anim_start;
+.float anim_end;
+
+.float dmg_time;
+
+float server_fps;
+
+#define VHEF_NORMAL 0
+#define VHEF_EJECT 1
+
+.void(float exit_flags) vehicle_exit;
+.void() vehicle_enter;
+.void() vehicle_die;
+.void() vehicle_spawn;
+.float(float message) vehicle_message;
+
+#include "vehicles.qc"
+#include "spiderbot.qc"
+#include "racer.qc"
+
+#endif
Property changes on: trunk/data/qcsrc/server/vehicles/vehicles.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: trunk/data/qcsrc/server/verbstack.qc
===================================================================
--- trunk/data/qcsrc/server/verbstack.qc 2009-06-30 13:36:51 UTC (rev 7130)
+++ trunk/data/qcsrc/server/verbstack.qc 2009-06-30 14:36:36 UTC (rev 7131)
@@ -1,200 +1,200 @@
-/// Some default stacks.
-.entity verbs_idle;
-.entity verbs_attack;
-.entity verbs_move;
-
-/// This global gets set to the verb in question each time the stack manager calls verb_call
-entity verb;
-
-/// Execure this verb
-#define VCM_DO 0
-/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
-#define VCM_EVAL 1
-/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
-#define VCM_REMOVE 2
-
-/// Verb callback
-.float(float message) verb_call;
-
-/// Points to this verb's stack.
-.entity verbstack;
-
-/// Static value of this verb
-.float verb_static_value;
-
-/// verb_call returns this when a verb in not doable
-#define VS_CALL_NO 0
-/// verb_call(VCM_DO) returns this when a verb is executing
-#define VS_CALL_YES_DOING -1
-/// verb_call(VCM_DO) returns this when a verb did execure and is done
-#define VS_CALL_YES_DONE -2
-/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
-#define VS_CALL_REMOVE -3
-
-/**
- Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
-**/
-entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
-{
- entity vrb;
-
- if not(stack)
- return world;
-
- if not(vrb_call)
- return world;
-
- vrb = spawn();
- vrb.owner = verb_owner;
- vrb.verbstack = stack;
- vrb.verb_call = vrb_call;
- vrb.verb_static_value = val_static;
-
- if(vrb_life)
- {
- vrb.think = SUB_Remove;
- vrb.nextthink = time + vrb_life;
- }
-
- return vrb;
-}
-
-/**
- Find the best verb in this stack and execurte it.
- ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
-**/
-float verbstack_pop(entity stack)
-{
- entity vrb, bestverb, oldself;
- float value, bestvalue;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- while(vrb)
- {
- verb = vrb;
- vrb = vrb.chain;
- self = verb.owner;
- value = verb.verb_call(VCM_EVAL);
-
- if(value < 0)
- {
- if(value == VS_CALL_REMOVE)
- remove(verb);
- }
- else
- {
- if(value > bestvalue)
- {
- bestverb = verb;
- bestvalue = value;
- }
- }
- }
-
- if(bestverb)
- {
- verb = bestverb;
- self = verb.owner;
- value = verb.verb_call(VCM_DO);
-
- if(value == VS_CALL_REMOVE)
- remove(bestverb);
- }
-
- self = oldself;
-
- return value;
-}
-
-float verbstack_popfifo(entity stack)
-{
- entity oldself;
- float ret;
-
- oldself = self;
- verb = findentity(stack,verbstack,stack);
- if not (verb)
- ret = 0;
- else
- {
- self = verb.owner;
- ret = verb.verb_call(VCM_DO);
-
- if(ret == VS_CALL_REMOVE)
- remove(verb);
- }
-
- self = oldself;
- return ret;
-}
-
-/**
- Find the best verb in this stack and return it.
- ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
-**/
-entity verbstack_pull(entity stack)
-{
- entity vrb;
- entity bestverb, oldself;
- float value, bestvalue;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- while(vrb)
- {
- self = vrb.owner;
-
- verb = vrb;
- vrb = vrb.chain;
- value = verb.verb_call(VCM_EVAL);
-
- if(value > 0)
- {
- if(value == VS_CALL_REMOVE)
- remove(verb);
- }
- else
- {
- if(value > bestvalue)
- {
- bestverb = verb;
- bestvalue = value;
- }
- }
- }
-
- self = oldself;
-
- return bestverb;
-}
-
-entity verbstack_pullfifo(entity stack)
-{
- return findentity(stack,verbstack,stack);
-}
-
-/**
- Delete every verb on this stack, signaling them with VCM_REMOVE first.
-**/
-void verbstack_flush(entity stack)
-{
- entity vrb, oldself;
-
- oldself = self;
-
- vrb = findchainentity(verbstack,stack);
- while(vrb)
- {
- self = vrb.owner;
-
- verb = vrb;
- vrb = vrb.chain;
- verb.verb_call(VCM_REMOVE);
- remove(verb);
- }
-
- self = oldself;
-}
+/// Some default stacks.
+.entity verbs_idle;
+.entity verbs_attack;
+.entity verbs_move;
+
+/// This global gets set to the verb in question each time the stack manager calls verb_call
+entity verb;
+
+/// Execure this verb
+#define VCM_DO 0
+/// Return the value of this verb. Return VS_CALL_REMOVE to delete it.
+#define VCM_EVAL 1
+/// This verb is beeing removed NOW (not sent when verb_call returns VS_CALL_REMOVE)
+#define VCM_REMOVE 2
+
+/// Verb callback
+.float(float message) verb_call;
+
+/// Points to this verb's stack.
+.entity verbstack;
+
+/// Static value of this verb
+.float verb_static_value;
+
+/// verb_call returns this when a verb in not doable
+#define VS_CALL_NO 0
+/// verb_call(VCM_DO) returns this when a verb is executing
+#define VS_CALL_YES_DOING -1
+/// verb_call(VCM_DO) returns this when a verb did execure and is done
+#define VS_CALL_YES_DONE -2
+/// verb_call(VCM_DO) returns this when a verb should be deleted by the stack manager
+#define VS_CALL_REMOVE -3
+
+/**
+ Push a new verb onto the specified stack. Set vrb_life to make it time-limited.
+**/
+entity verbstack_push(entity stack, float(float eval) vrb_call, float val_static, float vrb_life,entity verb_owner)
+{
+ entity vrb;
+
+ if not(stack)
+ return world;
+
+ if not(vrb_call)
+ return world;
+
+ vrb = spawn();
+ vrb.owner = verb_owner;
+ vrb.verbstack = stack;
+ vrb.verb_call = vrb_call;
+ vrb.verb_static_value = val_static;
+
+ if(vrb_life)
+ {
+ vrb.think = SUB_Remove;
+ vrb.nextthink = time + vrb_life;
+ }
+
+ return vrb;
+}
+
+/**
+ Find the best verb in this stack and execurte it.
+ ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL or VCM_DO
+**/
+float verbstack_pop(entity stack)
+{
+ entity vrb, bestverb, oldself;
+ float value, bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ verb = vrb;
+ vrb = vrb.chain;
+ self = verb.owner;
+ value = verb.verb_call(VCM_EVAL);
+
+ if(value < 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(verb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = verb;
+ bestvalue = value;
+ }
+ }
+ }
+
+ if(bestverb)
+ {
+ verb = bestverb;
+ self = verb.owner;
+ value = verb.verb_call(VCM_DO);
+
+ if(value == VS_CALL_REMOVE)
+ remove(bestverb);
+ }
+
+ self = oldself;
+
+ return value;
+}
+
+float verbstack_popfifo(entity stack)
+{
+ entity oldself;
+ float ret;
+
+ oldself = self;
+ verb = findentity(stack,verbstack,stack);
+ if not (verb)
+ ret = 0;
+ else
+ {
+ self = verb.owner;
+ ret = verb.verb_call(VCM_DO);
+
+ if(ret == VS_CALL_REMOVE)
+ remove(verb);
+ }
+
+ self = oldself;
+ return ret;
+}
+
+/**
+ Find the best verb in this stack and return it.
+ ALso remove any verbs returning VS_CALL_REMOVE on VCM_EVAL.
+**/
+entity verbstack_pull(entity stack)
+{
+ entity vrb;
+ entity bestverb, oldself;
+ float value, bestvalue;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ self = vrb.owner;
+
+ verb = vrb;
+ vrb = vrb.chain;
+ value = verb.verb_call(VCM_EVAL);
+
+ if(value > 0)
+ {
+ if(value == VS_CALL_REMOVE)
+ remove(verb);
+ }
+ else
+ {
+ if(value > bestvalue)
+ {
+ bestverb = verb;
+ bestvalue = value;
+ }
+ }
+ }
+
+ self = oldself;
+
+ return bestverb;
+}
+
+entity verbstack_pullfifo(entity stack)
+{
+ return findentity(stack,verbstack,stack);
+}
+
+/**
+ Delete every verb on this stack, signaling them with VCM_REMOVE first.
+**/
+void verbstack_flush(entity stack)
+{
+ entity vrb, oldself;
+
+ oldself = self;
+
+ vrb = findchainentity(verbstack,stack);
+ while(vrb)
+ {
+ self = vrb.owner;
+
+ verb = vrb;
+ vrb = vrb.chain;
+ verb.verb_call(VCM_REMOVE);
+ remove(verb);
+ }
+
+ self = oldself;
+}
Property changes on: trunk/data/qcsrc/server/verbstack.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/vote.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/vote.qh
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_campingrifle.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_hlac.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_hook.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_minstanex.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_porto.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_seeker.qc
___________________________________________________________________
Name: svn:eol-style
+ native
Property changes on: trunk/data/qcsrc/server/w_tuba.qc
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the nexuiz-commits
mailing list