r4365 - in branches/nexuiz-2.0: . Docs Docs/server data data/gfx data/maps data/models data/models/weapons data/qcsrc/client data/qcsrc/common data/qcsrc/menu/nexuiz data/qcsrc/server data/scripts data/textures
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Sep 5 15:40:38 EDT 2008
Author: div0
Date: 2008-09-05 15:40:34 -0400 (Fri, 05 Sep 2008)
New Revision: 4365
Added:
branches/nexuiz-2.0/data/gfx/inv_weapon10.tga
branches/nexuiz-2.0/data/gfx/inv_weapon9.tga
branches/nexuiz-2.0/data/models/portal.md3
branches/nexuiz-2.0/data/models/weapons/g_minstanex.md3
branches/nexuiz-2.0/data/models/weapons/g_porto.md3
branches/nexuiz-2.0/data/models/weapons/v_minstanex.md3
branches/nexuiz-2.0/data/models/weapons/v_porto.md3
branches/nexuiz-2.0/data/models/weapons/w_minstanex.zym
branches/nexuiz-2.0/data/models/weapons/w_porto.zym
branches/nexuiz-2.0/data/qcsrc/server/portals.qc
branches/nexuiz-2.0/data/qcsrc/server/portals.qh
branches/nexuiz-2.0/data/qcsrc/server/w_minstanex.qc
branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc
branches/nexuiz-2.0/data/textures/nex.tga
branches/nexuiz-2.0/data/textures/nex_bump.tga
branches/nexuiz-2.0/data/textures/nex_gloss.tga
branches/nexuiz-2.0/data/textures/nex_glow.tga
branches/nexuiz-2.0/data/textures/nex_pants.tga
branches/nexuiz-2.0/data/textures/nex_shirt.tga
branches/nexuiz-2.0/data/textures/portalgun.tga
branches/nexuiz-2.0/data/textures/portalgun_gloss.tga
branches/nexuiz-2.0/data/textures/portalgun_glow.tga
branches/nexuiz-2.0/data/textures/portalgun_norm.tga
Modified:
branches/nexuiz-2.0/.patchsets
branches/nexuiz-2.0/Docs/FAQ.aft
branches/nexuiz-2.0/Docs/FAQ.html
branches/nexuiz-2.0/Docs/server/server.cfg
branches/nexuiz-2.0/changes-since-last-release
branches/nexuiz-2.0/data/defaultNexuiz.cfg
branches/nexuiz-2.0/data/keybinds.txt
branches/nexuiz-2.0/data/maps/dieselpower.bsp
branches/nexuiz-2.0/data/maps/dieselpower.map
branches/nexuiz-2.0/data/qcsrc/client/Main.qc
branches/nexuiz-2.0/data/qcsrc/client/View.qc
branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc
branches/nexuiz-2.0/data/qcsrc/client/main.qh
branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
branches/nexuiz-2.0/data/qcsrc/common/constants.qh
branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc
branches/nexuiz-2.0/data/qcsrc/common/util.qc
branches/nexuiz-2.0/data/qcsrc/common/util.qh
branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_mutators.c
branches/nexuiz-2.0/data/qcsrc/server/builtins.qh
branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
branches/nexuiz-2.0/data/qcsrc/server/cl_impulse.qc
branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc
branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
branches/nexuiz-2.0/data/qcsrc/server/constants.qh
branches/nexuiz-2.0/data/qcsrc/server/defs.qh
branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
branches/nexuiz-2.0/data/qcsrc/server/progs.src
branches/nexuiz-2.0/data/qcsrc/server/race.qc
branches/nexuiz-2.0/data/qcsrc/server/scores.qc
branches/nexuiz-2.0/data/qcsrc/server/scores.qh
branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc
branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc
branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
branches/nexuiz-2.0/data/qcsrc/server/w_common.qc
branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc
branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc
branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc
branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc
branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc
branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc
branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc
branches/nexuiz-2.0/data/qcsrc/server/w_shotgun.qc
branches/nexuiz-2.0/data/qcsrc/server/w_uzi.qc
branches/nexuiz-2.0/data/scripts/entities.def
branches/nexuiz-2.0/data/weapons.cfg
branches/nexuiz-2.0/data/weaponsPro.cfg
Log:
fix attack_finished bug blocking weapon switching
weapon priority lists; non-critical impulses reordered (cleaned up)
fix inverted condition in func_door_secret
i wanna see the packetloss with sbar_columns all
Dieselpower: Changed MG ammo to SG ammo. There is no MG here.
Added new entity: "func_breakable"; functions the same way func_assault_destructible does, but it's for general gameplay use (IE destructible glass, crates, etc.)
enabled chat flood protection by default
support teamed items
g_weaponreplace_*
Capitalize some words in the FAQ
renamed g_tourney_warmup_unlimited_time to g_tourney_warmup_limit and default it to 60 (-1 is totally unlimited, 0 is up to timelimit, other values limit it further)
being limited to 60 seconds, next step is to enable g_tourney too by default (i think CSQC needs to show this in a good way first, we try this later)
do not require items in Race
maybe missing initialization breaks ready-restart so much on my ctf server?
Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/.patchsets 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,2 +1,2 @@
master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-4273
+revisions_applied = 1-4363
Modified: branches/nexuiz-2.0/Docs/FAQ.aft
===================================================================
--- branches/nexuiz-2.0/Docs/FAQ.aft 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/Docs/FAQ.aft 2008-09-05 19:40:34 UTC (rev 4365)
@@ -48,6 +48,9 @@
4. the engine could not initialize OpenGL. Please install the latest drivers for your graphic card. You will probably find one for your card there: [intel (http://intel.com)] [ati (http://ati.com)] [nvidia (http://nvidia.com)]
5. your download might be corrupted, please download Nexuiz again
+** When i start Nexuiz my screen is flickering
+This in known to happen on Windows with Intel grahpic chips and is a bug in the graphics drivers. A workaround is to set |Flip-Policiy| to |blit|. Open the control panel, there should be an icon called |Intel(R) GMA driver| (or something like that), double click it. Click on |3D Settings| to find the screen with that settings.
+
** How can I speed up my frame rate?
You can choose predefined performance settings in the |Settings / Video| menu. |Normal| is the default, |Medium| and |Low| run faster while |High|, |Ultra| and |Ultimate| enable more features you might want to test if you have a high end graphic card. Or you can dis/enable single features. The greatest performance boost can be achieved by turning off dynamic lights and shadows in the |Settings / Effects| menu. Bloom is also quite resource intensive. Other fps boots include disabling |Deluxemapping| and |Coronas|. On older graphics cards or on-board/notebook chips with little video ram you can try to lower the texture quality in the |Settings / Video| menu.
Some graphic cards (mostly ATI or quite old cards) run A LOT faster if you disable the |Vertex Buffer Objects| in the |Settings / Video| menu. An other thing that can greatly help on such cards is to disable the |OpenGL 2.0 Shaders|. Having that option enabled is faster on most cards however thats why both are active by default.
Modified: branches/nexuiz-2.0/Docs/FAQ.html
===================================================================
--- branches/nexuiz-2.0/Docs/FAQ.html 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/Docs/FAQ.html 2008-09-05 19:40:34 UTC (rev 4365)
@@ -125,6 +125,7 @@
<ul>
<li> <a class="link" href="#How do I install Nexuiz?">How do I install Nexuiz?</a></li>
<li> <a class="link" href="#When I start Nexuiz all I see is a black screen or a black screen with some checkered squares">When I start Nexuiz all I see is a black screen or a black screen with some checkered squares</a></li>
+<li> <a class="link" href="#When i start Nexuiz my screen is flickering">When i start Nexuiz my screen is flickering</a></li>
<li> <a class="link" href="#How can I speed up my frame rate?">How can I speed up my frame rate?</a></li>
<li> <a class="link" href="#The sound is broken, it crackles and stutters">The sound is broken, it crackles and stutters</a></li>
<li> <a class="link" href="#Mouse is too slow and sensitivity is at top (on Mac / Linux)">Mouse is too slow and sensitivity is at top (on Mac / Linux)</a></li>
@@ -199,6 +200,11 @@
</ol>
</p>
<!--End Section 2-->
+<h3><a name="When i start Nexuiz my screen is flickering">When i start Nexuiz my screen is flickering</a></h3>
+<p class="Body">
+This in known to happen on Windows with Intel grahpic chips and is a bug in the graphics drivers. A workaround is to set <tt>Flip-Policiy</tt> to <tt>blit</tt>. Open the control panel, there should be an icon called <tt>Intel(R) GMA driver</tt> (or something like that), double click it. Click on <tt>3D Settings</tt> to find the screen with that settings.
+</p>
+<!--End Section 2-->
<h3><a name="How can I speed up my frame rate?">How can I speed up my frame rate?</a></h3>
<p class="Body">
You can choose predefined performance settings in the <tt>Settings / Video</tt> menu. <tt>Normal</tt> is the default, <tt>Medium</tt> and <tt>Low</tt> run faster while <tt>High</tt>, <tt>Ultra</tt> and <tt>Ultimate</tt> enable more features you might want to test if you have a high end graphic card. Or you can dis/enable single features. The greatest performance boost can be achieved by turning off dynamic lights and shadows in the <tt>Settings / Effects</tt> menu. Bloom is also quite resource intensive. Other fps boots include disabling <tt>Deluxemapping</tt> and <tt>Coronas</tt>. On older graphics cards or on-board/notebook chips with little video ram you can try to lower the texture quality in the <tt>Settings / Video</tt> menu.
Modified: branches/nexuiz-2.0/Docs/server/server.cfg
===================================================================
--- branches/nexuiz-2.0/Docs/server/server.cfg 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/Docs/server/server.cfg 2008-09-05 19:40:34 UTC (rev 4365)
@@ -50,7 +50,6 @@
//sv_gravity 800 // for low gravity, set this somewhere between 50 and 400
// select AT MOST one of these arena mutators
-//g_instagib 0 // set to 1 to make the Nex the only weapon
//g_minstagib 0 // set to 1 for MinstaGib
//g_nixnex 0 // set to 1 for No Items Nexuiz
//g_nixnex_with_laser 0 // set to 1 to always give players the laser in NixNex
@@ -76,7 +75,7 @@
//g_maplist_votable_abstain 0 // when 1, people get a "don't care" selection in the vote screen
//g_maplist_votable_nodetail 1 // when 1, people can't see how many voted for what (to thwart abusive "influential" first votes)
-//sv_vote_commands "restart timelimit fraglimit chmap gotomap g_grappling_hook sv_defaultplayer_fbskin_green sv_defaultplayer_fbskin_red sv_defaultplayer_fbskin_orange sv_defaultplayer_fbskin_off" // players can vote for those commands or use them if they are masters
+//sv_vote_commands "restart timelimit fraglimit chmap gotomap g_grappling_hook sv_defaultplayer_fbskin_green sv_defaultplayer_fbskin_red sv_defaultplayer_fbskin_orange sv_defaultplayer_fbskin_off endmatch reducematchtime extendmatchtime allready" // players can vote for those commands or use them if they are masters
//sv_vote_call 1 // 0 will disable the normal voting
//sv_vote_master 1 // 0 will disable voting to become masters
//sv_vote_master_password "" // when set, vdo login master will allow you to run votable commands directly using vdo
Modified: branches/nexuiz-2.0/changes-since-last-release
===================================================================
--- branches/nexuiz-2.0/changes-since-last-release 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/changes-since-last-release 2008-09-05 19:40:34 UTC (rev 4365)
@@ -28,7 +28,6 @@
game: hook can pull players (but detaches when that player shoots you)
game: hook detaches when teleporting
game: hook jitter-less
-game: hook no longer goes through walls
game: hook sky-attach bug fixed
game: item respawn: 20s for 50health and 25armor
game: lemmings countdown ;)
Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg 2008-09-05 19:40:34 UTC (rev 4365)
@@ -138,7 +138,7 @@
//tournament mod
set g_tourney 0 //enables tourney mode which splits the game into a warmup- and match-stage
-set g_tourney_warmup_unlimited_time 1 //if set the warmup-stage is not affected by any timelimit, otherwise the usual timelimit also affects warmup-stage
+set g_tourney_warmup_limit 60 //if set to -1 the warmup-stage is not affected by any timelimit, if set to 0 the usual timelimit also affects warmup-stage, otherwise warmup will be limited to this time (useful for public matches)
set g_tourney_warmup_allow_timeout 0 //if set to 0 you cannot use the calltimeout command during the warmup-stage but only during the match stage
set g_tourney_disable_spec_chat 1 //if set the chat sent by spectators or observers while being in match-stage can only seen by other specs/observers
set g_tourney_disable_spec_vote 1 //if set only players can call a vote during the match-stage (thus spectators and observers can't call a vote then)
@@ -270,7 +270,6 @@
set g_powerup_shield 1
set g_use_ammunition 1
set g_pickup_items 1
-set g_instagib 0
set g_minstagib 0 // enable minstagib
set g_minstagib_extralives 2 // how many extra lives you will get per powerup
set g_minstagib_ammo_start 10 // starting ammo
@@ -613,7 +612,7 @@
bind 7 "impulse 7"
bind 8 "impulse 8"
bind 9 "impulse 9"
-bind 0 "impulse 210"
+bind 0 "impulse 14" // cycles the superweapons
bind MOUSE1 +attack
bind MOUSE2 +attack2
bind MOUSE3 +zoom
@@ -830,14 +829,14 @@
seta g_maplist_textonly 0 // use old style centerprint
alias suggestmap "cmd suggestmap $1"
-set g_chat_flood_spl 0 // seconds between lines to not count as flooding
-set g_chat_flood_lmax 0 // maximum number of lines per chat message at once
-set g_chat_flood_burst 0 // allow bursts of so many chat lines
-set g_chat_flood_spl_team 0 // \
-set g_chat_flood_lmax_team 0 // } same for say_team
-set g_chat_flood_burst_team 0 // /
-set g_chat_flood_notify_flooder 1 // when 0, the flooder still can see his own message
-set g_chat_teamcolors 0 // colorize nicknames in team color for chat
+set g_chat_flood_spl 3 // seconds between lines to not count as flooding
+set g_chat_flood_lmax 2 // maximum number of lines per chat message at once
+set g_chat_flood_burst 2 // allow bursts of so many chat lines
+set g_chat_flood_spl_team 1 // \
+set g_chat_flood_lmax_team 2 // } same for say_team
+set g_chat_flood_burst_team 2 // /
+set g_chat_flood_notify_flooder 1 // when 0, the flooder still can see his own message
+set g_chat_teamcolors 0 // colorize nicknames in team color for chat
set g_waypointsprite_normdistance 512
set g_waypointsprite_minscale 1
@@ -1077,3 +1076,33 @@
set g_jump_grunt 0 // Do you make a grunting noise every time you jump? Is it the same grunting noise every time?
alias allready "sv_cmd allready"
+
+seta cl_weaponpriority "10 9 8 11 7 6 5 4 3 2 1"
+// impulse 200, 210, 220:
+seta cl_weaponpriority0 "9 8 4" // explosives (RL Hagar Mortar)
+// impulse 201, 211, 221:
+seta cl_weaponpriority1 "7 6 5 1" // energy (Nex Crylink Electro Laser)
+seta cl_weaponpriority2 "7 3" // hitscan exact (Nex MG)
+seta cl_weaponpriority3 "7 3 2" // hitscan all (Nex MG Shotgun)
+seta cl_weaponpriority4 "8 6 5 2" // spam (Hagar Crylink Electro Shotgun)
+seta cl_weaponpriority5 ""
+seta cl_weaponpriority6 ""
+seta cl_weaponpriority7 ""
+seta cl_weaponpriority8 ""
+// impulse 209, 219, 229:
+seta cl_weaponpriority9 ""
+
+// NOTE: this only replaces weapons on the map
+// use g_start_weapon_* to also replace the on-startup weapons!
+// example: g_weaponreplace_7 "7 11", then Nexes become MinstaNexes 50% of the times
+set g_weaponreplace_1 ""
+set g_weaponreplace_2 ""
+set g_weaponreplace_3 ""
+set g_weaponreplace_4 ""
+set g_weaponreplace_5 ""
+set g_weaponreplace_6 ""
+set g_weaponreplace_7 ""
+set g_weaponreplace_8 ""
+set g_weaponreplace_9 ""
+set g_weaponreplace_10 ""
+set g_weaponreplace_11 ""
Copied: branches/nexuiz-2.0/data/gfx/inv_weapon10.tga (from rev 4363, trunk/data/gfx/inv_weapon10.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/gfx/inv_weapon9.tga (from rev 4363, trunk/data/gfx/inv_weapon9.tga)
===================================================================
(Binary files differ)
Modified: branches/nexuiz-2.0/data/keybinds.txt
===================================================================
--- branches/nexuiz-2.0/data/keybinds.txt 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/keybinds.txt 2008-09-05 19:40:34 UTC (rev 4365)
@@ -24,6 +24,7 @@
"impulse 7" "nex"
"impulse 8" "hagar"
"impulse 9" "rocket launcher"
+"impulse 14" "special weapons"
"" ""
"" "View"
"+zoom" "zoom"
Modified: branches/nexuiz-2.0/data/maps/dieselpower.bsp
===================================================================
(Binary files differ)
Modified: branches/nexuiz-2.0/data/maps/dieselpower.map
===================================================================
--- branches/nexuiz-2.0/data/maps/dieselpower.map 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/maps/dieselpower.map 2008-09-05 19:40:34 UTC (rev 4365)
@@ -25408,7 +25408,7 @@
// entity 12
{
"origin" "1232 -864 -1008"
-"classname" "ammo_bullets"
+"classname" "ammo_shells"
}
// entity 13
{
@@ -25519,7 +25519,7 @@
// entity 31
{
"origin" "816 912 -232"
-"classname" "ammo_bullets"
+"classname" "ammo_shells"
}
// entity 32
{
Copied: branches/nexuiz-2.0/data/models/portal.md3 (from rev 4363, trunk/data/models/portal.md3)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/g_minstanex.md3 (from rev 4363, trunk/data/models/weapons/g_minstanex.md3)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/g_porto.md3 (from rev 4363, trunk/data/models/weapons/g_porto.md3)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/v_minstanex.md3 (from rev 4363, trunk/data/models/weapons/v_minstanex.md3)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/v_porto.md3 (from rev 4363, trunk/data/models/weapons/v_porto.md3)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/w_minstanex.zym (from rev 4363, trunk/data/models/weapons/w_minstanex.zym)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/models/weapons/w_porto.zym (from rev 4363, trunk/data/models/weapons/w_porto.zym)
===================================================================
(Binary files differ)
Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -187,6 +187,7 @@
self.nextthink = time + 0.2;
}
+void Porto_Init();
void PostInit(void)
{
print(strcat("PostInit\n maxclients = ", ftos(maxclients), "\n"));
@@ -197,6 +198,8 @@
playerchecker.think = Playerchecker_Think;
playerchecker.nextthink = time + 0.2;
+ Porto_Init();
+
postinit = true;
}
@@ -623,10 +626,11 @@
void Net_ReadInit()
{
+ float i;
csqc_revision = ReadShort();
maxclients = ReadByte();
- minstagib = ReadByte();
-
+ for(i = 0; i < 24; ++i)
+ weaponimpulse[i] = ReadByte() - 1;
CSQC_CheckRevision();
}
@@ -763,6 +767,7 @@
// 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.
+void Net_ReadHoldAngles();
float CSQC_Parse_TempEntity()
{
local float bHandled;
@@ -814,6 +819,10 @@
Net_ReadZoomNotify();
bHandled = true;
break;
+ case TE_CSQC_HOLDANGLES:
+ Net_ReadHoldAngles();
+ bHandled = true;
+ break;
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
bHandled = false;
Modified: branches/nexuiz-2.0/data/qcsrc/client/View.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/View.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/client/View.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,5 +1,102 @@
-//include "main.qh"
+float angles_held_status[24];
+vector angles_held[24];
+void Net_ReadHoldAngles()
+{
+ float wpn;
+ vector v;
+ wpn = ReadByte();
+ --wpn;
+ angles_held_status[wpn] = ReadByte();
+ if(angles_held_status[wpn])
+ {
+ v_x = ReadCoord();
+ v_y = ReadCoord();
+ v_z = 0;
+ angles_held[wpn] = v;
+ }
+}
+entity porto;
+vector polyline[16];
+float Q3SURFACEFLAG_SLICK = 2; // low friction surface
+void Porto_Draw()
+{
+ vector p, dir, ang, q, nextdir;
+ float idx, portal_number, portal1_idx;
+
+ if(activeweapon != WEP_PORTO)
+ return;
+
+ dir = view_forward;
+
+ if(angles_held_status[WEP_PORTO-1])
+ {
+ makevectors(angles_held[WEP_PORTO-1]);
+ 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, world);
+ 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)
+ continue;
+ ++portal_number;
+ ang = vectoangles(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;
+ }
+}
+
+float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box
+float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel
+float DPCONTENTS_PLAYERCLIP = 256; // blocks player movement
+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)
@@ -28,7 +125,7 @@
zoomspeed = 3.5;
zoomdir = button_zoom;
- if(activeweapon == 7 && !minstagib)
+ if(activeweapon == WEP_NEX)
zoomdir += button_attack2;
if(spectatee_status > 0 || isdemo())
{
@@ -121,7 +218,7 @@
sbar_alpha_fg = cvar("sbar_alpha_fg" );
sbar_hudselector = cvar("sbar_hudselector");
- activeweapon = getstati(STAT_ACTIVEWEAPON);
+ activeweapon = getstati(STAT_SWITCHWEAPON);
teamplay = cvar("teamplay");
if(last_weapon != activeweapon) {
Modified: branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/client/csqc_constants.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -164,24 +164,6 @@
const float BUTTON_16 = 262144;
-const float NEX_IT_UZI = 1;
-const float NEX_IT_SHOTGUN = 2;
-const float NEX_IT_GRENADE_LAUNCHER = 4;
-const float NEX_IT_ELECTRO = 8;
-const float NEX_IT_CRYLINK = 16;
-const float NEX_IT_NEX = 32;
-const float NEX_IT_HAGAR = 64;
-const float NEX_IT_ROCKET_LAUNCHER = 128;
-const float NEX_IT_SHELLS = 256;
-const float NEX_IT_BULLETS = 512;
-const float NEX_IT_ROCKETS = 1024;
-const float NEX_IT_CELLS = 2048;
-const float NEX_IT_LASER = 4094;
-const float NEX_IT_STRENGTH = 8192;
-const float NEX_IT_INVINCIBLE = 16384;
-const float NEX_IT_SPEED = 32768;
-const float NEX_IT_SLOWMO = 65536;
-
const float DRAWFLAG_NORMAL = 0;
const float DRAWFLAG_ADDITIVE = 1;
const float DRAWFLAG_MODULATE = 2;
Modified: branches/nexuiz-2.0/data/qcsrc/client/main.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/main.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/client/main.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -118,8 +118,9 @@
float spectatorbutton_zoom;
float button_attack2;
float activeweapon;
-float minstagib;
float current_viewzoom;
float zoomin_effect;
float ignore_plus_zoom;
float ignore_minus_zoom;
+
+float weaponimpulse[24];
Modified: branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/sbar.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/client/sbar.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -27,10 +27,35 @@
MapVote_Draw();
}
+float weaponspace[10];
+float weapon_first, weapon_last;
+void Sbar_DrawWeapon_Clear()
+{
+ float idx;
+ weapon_first = -2;
+ weapon_last = -1;
+ for(idx = 0; idx < 10; ++idx)
+ weaponspace[idx] = 0;
+ for(idx = 0; idx <= 23; ++idx)
+ {
+ if(weaponimpulse[idx] >= 0)
+ {
+ if(weapon_first < 0)
+ weapon_first = idx;
+ weapon_last = idx;
+ }
+ }
+}
void Sbar_DrawWeapon(float nr, float fade, float active)
{
vector pos, vsize, color;
- float value;
+ float value, idx, imp, sp;
+
+ imp = weaponimpulse[nr];
+ if(imp == 0)
+ idx = 9;
+ else
+ idx = imp - 1;
value = (active) ? 1 : 0.6;
color_x = color_y = color_z = value;
@@ -39,9 +64,12 @@
{
// width = 300, height = 100
const float w_width = 32, w_height = 12, w_space = 2, font_size = 8;
+
+ sp = weaponspace[idx] + 1;
+ weaponspace[idx] = sp;
- pos_x = (vid_conwidth - w_width * 9) * 0.5 + w_width * nr;
- pos_y = (vid_conheight - w_height);
+ pos_x = (vid_conwidth - w_width * 9) * 0.5 + w_width * idx;
+ pos_y = (vid_conheight - w_height * sp);
pos_z = 0;
vsize_x = w_width;
vsize_y = w_height;
@@ -52,8 +80,7 @@
vsize_x = font_size;
vsize_y = font_size;
vsize_z = 0;
- drawstring(pos, ftos(nr+1), vsize, '1 1 0', sbar_alpha_fg, 0);
-
+ drawstring(pos, ftos(imp), vsize, '1 1 0', sbar_alpha_fg, 0);
}
else
{
@@ -61,11 +88,14 @@
const float w2_width = 300, w2_height = 100, w2_space = 10;
const float w2_scale = 0.4;
- pos_x = vid_conwidth - (w2_width + w2_space) * w2_scale;
- pos_y = (w2_height + w2_space) * w2_scale * nr + w2_space;
+ float f;
+ f = 9 / (weapon_last + 1 - weapon_first);
+
+ pos_x = vid_conwidth - (w2_width + w2_space) * w2_scale * f;
+ pos_y = (w2_height + w2_space) * w2_scale * nr * f + w2_space;
pos_z = 0;
- vsize_x = w2_width * w2_scale;
- vsize_y = w2_height * w2_scale;
+ vsize_x = w2_width * w2_scale * f;
+ vsize_y = w2_height * w2_scale * f;
vsize_z = 0;
drawpic(pos, strcat("gfx/inv_weapon", ftos(nr)), vsize, color, value * fade * sbar_alpha_fg, 0);
@@ -341,7 +371,7 @@
else if(argv(1) == "all")
{
string s;
- s = "ping name |";
+ s = "ping pl name |";
for(i = 0; i < MAX_SCORE; ++i)
{
if(i != ps_primary)
@@ -1296,7 +1326,7 @@
{
float i;
float x, fade;
- float stat_items;
+ float stat_items, stat_weapons;
sbar_fontsize = Sbar_GetFontsize();
@@ -1402,6 +1432,7 @@
if (sb_lines && sbar_hudselector == 1)
{
stat_items = getstati(STAT_ITEMS);
+ stat_weapons = getstati(STAT_WEAPONS);
sbar_x = (vid_conwidth - 320.0)*0.5;
sbar_y = vid_conheight - 24.0 - 16.0;
@@ -1411,19 +1442,16 @@
fade = bound(0.7, fade, 1);
x = 1.0;
- for(i = 0; i < 8; ++i)
+ Sbar_DrawWeapon_Clear();
+ for(i = 1; i <= 24; ++i)
{
- if(stat_items & x)
+ if(weaponimpulse[i-1] >= 0)
+ if(stat_weapons & x)
{
- Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
+ Sbar_DrawWeapon(i-1, fade, (i == activeweapon));
}
x *= 2;
}
- x *= 2*2*2*2;
- if(stat_items & x)
- {
- Sbar_DrawWeapon(0, fade, (activeweapon == 1));
- }
// armor
x = getstati(STAT_ARMOR);
@@ -1465,15 +1493,15 @@
// ammo
x = getstati(STAT_AMMO);
- if ((stat_items & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || x != 0)
+ if ((stat_items & IT_AMMO) || x != 0)
{
- if (stat_items & NEX_IT_SHELLS)
+ if (stat_items & IT_SHELLS)
drawpic(sbar + '296 0 0', "gfx/sb_shells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_BULLETS)
+ else if (stat_items & IT_NAILS)
drawpic(sbar + '296 0 0', "gfx/sb_bullets", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_ROCKETS)
+ else if (stat_items & IT_ROCKETS)
drawpic(sbar + '296 0 0', "gfx/sb_rocket", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_CELLS)
+ else if (stat_items & IT_CELLS)
drawpic(sbar + '296 0 0', "gfx/sb_cells", '24 24 0', '1 1 1', sbar_alpha_fg, 0);
if(x > 10)
Sbar_DrawXNum('224 0 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
@@ -1492,6 +1520,7 @@
{
stat_items = getstati(STAT_ITEMS);
+ stat_weapons = getstati(STAT_WEAPONS);
sbar_x = (vid_conwidth - 640.0)*0.5;
sbar_y = vid_conheight - 47;
@@ -1500,19 +1529,16 @@
fade = 3 - 2 * (time - weapontime);
x = 1.0;
- for(i = 0; i < 8; ++i)
+ Sbar_DrawWeapon_Clear();
+ for(i = 1; i <= 24; ++i)
{
- if(stat_items & x)
+ if(weaponimpulse[i-1] >= 0)
+ if(stat_weapons & x)
{
- Sbar_DrawWeapon(i+1, fade, (i + 2 == activeweapon));
+ Sbar_DrawWeapon(i-1, fade, (i == activeweapon));
}
x *= 2;
}
- x *= 2*2*2*2;
- if(stat_items & x)
- {
- Sbar_DrawWeapon(0, fade, (activeweapon == 1));
- }
if (sb_lines > 24)
drawpic(sbar, "gfx/sbar", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
@@ -1538,13 +1564,13 @@
if(activeweapon != 12)
{
// (519-3*24) = 447
- if (stat_items & NEX_IT_SHELLS)
+ if (stat_items & IT_SHELLS)
drawpic(sbar + '519 0 0', "gfx/sb_shells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_BULLETS)
+ else if (stat_items & IT_NAILS)
drawpic(sbar + '519 0 0', "gfx/sb_bullets", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_ROCKETS)
+ else if (stat_items & IT_ROCKETS)
drawpic(sbar + '519 0 0', "gfx/sb_rocket", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
- else if (stat_items & NEX_IT_CELLS)
+ else if (stat_items & IT_CELLS)
drawpic(sbar + '519 0 0', "gfx/sb_cells", '0 0 0', '1 1 1', sbar_alpha_fg, 0);
if(x > 10)
Sbar_DrawXNum('447 12 0', x, 3, 24, '0.6 0.7 0.8', 1, 0);
Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -14,7 +14,9 @@
// Revision 13: pointparticles
// Revision 14: laser
// Revision 15: zoom
-#define CSQC_REVISION 15
+// Revision 16: multi-weapons
+// Revision 17: multi-weaponimpulses
+#define CSQC_REVISION 17
// probably put these in common/
// so server/ and client/ can be synced better
@@ -200,10 +202,13 @@
const float TE_CSQC_SPECTATING = 111;
const float TE_CSQC_SPAWN = 112;
const float TE_CSQC_ZOOMNOTIFY = 113;
+const float TE_CSQC_HOLDANGLES = 114;
const float STAT_KH_KEYS = 32;
const float STAT_CTF_STATE = 33;
const float STAT_SYS_TICRATE = 34;
+const float STAT_WEAPONS = 35;
+const float STAT_SWITCHWEAPON = 36;
const float CTF_STATE_ATTACK = 1;
const float CTF_STATE_DEFEND = 2;
const float CTF_STATE_COMMANDER = 3;
@@ -270,3 +275,48 @@
#define SP_SUICIDES 2
#define SP_SCORE 3
// game mode specific indices are not in common/, but in server/scores_rules.qc!
+
+// Weapon indexes
+// %weaponaddpoint
+float WEP_FIRST = 1;
+float WEP_LASER = 1; float WEPBIT_LASER = 1; // always: 2^(w-1)
+float WEP_SHOTGUN = 2; float WEPBIT_SHOTGUN = 2;
+float WEP_UZI = 3; float WEPBIT_UZI = 4;
+float WEP_GRENADE_LAUNCHER = 4; float WEPBIT_GRENADE_LAUNCHER = 8;
+float WEP_ELECTRO = 5; float WEPBIT_ELECTRO = 16;
+float WEP_CRYLINK = 6; float WEPBIT_CRYLINK = 32;
+float WEP_NEX = 7; float WEPBIT_NEX = 64;
+float WEP_HAGAR = 8; float WEPBIT_HAGAR = 128;
+float WEP_ROCKET_LAUNCHER = 9; float WEPBIT_ROCKET_LAUNCHER = 256;
+float WEP_PORTO = 10; float WEPBIT_PORTO = 512;
+float WEP_MINSTANEX = 11; float WEPBIT_MINSTANEX = 1024;
+float WEP_LAST = 11; float WEPBIT_ALL = 2047;
+float WEP_COUNT = 12;
+
+float IT_UNLIMITED_AMMO = 1;
+// when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
+float IT_SHELLS = 256;
+float IT_NAILS = 512;
+float IT_ROCKETS = 1024;
+float IT_CELLS = 2048;
+float IT_SUPERWEAPON = 4096;
+float IT_AMMO = 7936;
+float IT_STRENGTH = 8192;
+float IT_INVINCIBLE = 16384;
+float IT_HEALTH = 32768;
+// union:
+ // for items:
+ float IT_KEY1 = 131072;
+ float IT_KEY2 = 262144;
+ // for players:
+ float IT_RED_FLAG_TAKEN = 32768;
+ float IT_RED_FLAG_LOST = 65536;
+ float IT_RED_FLAG_CARRING = 98304;
+ float IT_BLUE_FLAG_TAKEN = 131072;
+ float IT_BLUE_FLAG_LOST = 262144;
+ float IT_BLUE_FLAG_CARRING = 393216;
+// end
+float IT_5HP = 524288;
+float IT_25HP = 1048576;
+float IT_ARMOR_SHARD = 2097152;
+float IT_ARMOR = 4194304;
Modified: branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/common/mapinfo.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -788,7 +788,7 @@
{
float req;
req = 0;
- if(!(cvar("g_lms") || cvar("g_instagib") || cvar("g_minstagib") || cvar("g_nixnex") || cvar("g_rocketarena") || !cvar("g_pickup_items")))
+ if(!(cvar("g_lms") || cvar("g_instagib") || cvar("g_minstagib") || cvar("g_nixnex") || cvar("g_rocketarena") || !cvar("g_pickup_items") || cvar("g_race")))
req |= MAPINFO_FEATURE_WEAPONS;
return req;
}
Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -615,3 +615,28 @@
}
}
+#ifndef MENUQC
+float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz)
+{
+ traceline(v0, v0 + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0, v0 + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0, v0 + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvx, v0 + dvx + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvx, v0 + dvx + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvy, v0 + dvy + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvy, v0 + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvz, v0 + dvz + dvx, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvz, v0 + dvz + dvy, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvx + dvy, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvx + dvz, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ traceline(v0 + dvy + dvz, v0 + dvx + dvy + dvz, TRUE, forent); if(trace_fraction < 1) return 0;
+ return 1;
+}
+
+// a makevectors that inverts vectoangles
+void fixedmakevectors(vector a)
+{
+ a_x = -a_x;
+ makevectors(a);
+}
+#endif
Modified: branches/nexuiz-2.0/data/qcsrc/common/util.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/util.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/common/util.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -65,3 +65,9 @@
void compressShortVector_init();
vector decompressShortVector(float data);
float compressShortVector(vector vec);
+
+#ifndef MENUQC
+float CheckWireframeBox(entity forent, vector v0, vector dvx, vector dvy, vector dvz);
+
+void fixedmakevectors(vector a);
+#endif
Modified: branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_mutators.c
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_mutators.c 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/menu/nexuiz/dialog_multiplayer_create_mutators.c 2008-09-05 19:40:34 UTC (rev 4365)
@@ -22,8 +22,6 @@
{
string s;
s = "";
- if(cvar("g_instagib"))
- s = strcat(s, ", InstaGib");
if(cvar("g_minstagib"))
s = strcat(s, ", MinstaGib");
if(cvar("g_nixnex"))
@@ -72,8 +70,6 @@
me.TR(me);
me.TD(me, 1, 2, e = makeNexuizRadioButton(1, string_null, string_null, "Regular"));
me.TR(me);
- me.TD(me, 1, 2, e = makeNexuizRadioButton(1, "g_instagib", string_null, "InstaGib"));
- me.TR(me);
me.TD(me, 1, 2, e = makeNexuizRadioButton(1, "g_minstagib", string_null, "MinstaGib"));
me.TR(me);
me.TD(me, 1, 2, e = makeNexuizRadioButton(1, "g_nixnex", string_null, "NixNex"));
Modified: branches/nexuiz-2.0/data/qcsrc/server/builtins.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/builtins.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/builtins.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -49,7 +49,7 @@
void particle (vector v, vector d, float colour, float count) = #48;
void ChangeYaw (void) = #49;
-vector vectoangles (vector v) = #51;
+vector vectoangles (vector v, ...) = #51;
void(float to, float f) WriteByte = #52;
void(float to, float f) WriteChar = #53;
void(float to, float f) WriteShort = #54;
Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -401,6 +401,8 @@
DropAllRunes(self);
kh_Key_DropAll(self, TRUE);
+ Portal_ClearAll(self);
+
if(self.flagcarried)
DropFlag(self.flagcarried);
@@ -461,6 +463,7 @@
setsize (self, '0 0 0', '0 0 0');
self.oldorigin = self.origin;
self.items = 0;
+ self.weapons = 0;
self.model = "";
self.modelindex = 0;
self.weapon = 0;
@@ -631,6 +634,7 @@
self.health = start_health;
self.armorvalue = start_armorvalue;
self.items = start_items;
+ self.weapons = start_weapons;
self.switchweapon = start_switchweapon;
self.cnt = start_switchweapon;
self.weapon = 0;
@@ -767,6 +771,7 @@
*/
void SendCSQCInfo(void)
{
+ float i;
if(clienttype(self) != CLIENTTYPE_REAL)
return;
msg_entity = self;
@@ -774,7 +779,8 @@
WriteByte(MSG_ONE, TE_CSQC_INIT);
WriteShort(MSG_ONE, CSQC_REVISION);
WriteByte(MSG_ONE, maxclients);
- WriteByte(MSG_ONE, g_minstagib);
+ for(i = 1; i <= 24; ++i)
+ WriteByte(MSG_ONE, (get_weaponinfo(i)).impulse + 1);
}
/*
@@ -1029,7 +1035,6 @@
void ClientConnect (void)
{
local string s;
- float wep;
if(self.flags & FL_CLIENT)
{
@@ -1123,15 +1128,6 @@
// get version info from player
stuffcmd(self, "cmd clientversion $gameversion\n");
- // send all weapon info strings
- stuffcmd(self, "register_bestweapon clear\n"); // clear the Quake stuff
- wep = WEP_FIRST;
- while (wep <= WEP_LAST)
- {
- weapon_action(wep, WR_REGISTER);
- wep = wep + 1;
- }
-
// get other cvars from player
GetCvars(0);
@@ -1260,6 +1256,8 @@
DropAllRunes(self);
kh_Key_DropAll(self, TRUE);
+ Portal_ClearAll(self);
+
if(self.flagcarried)
DropFlag(self.flagcarried);
@@ -1683,6 +1681,7 @@
self.health = spectatee.health;
self.impulse = 0;
self.items = spectatee.items;
+ self.weapons = spectatee.weapons;
self.punchangle = spectatee.punchangle;
self.view_ofs = spectatee.view_ofs;
self.v_angle = spectatee.v_angle;
@@ -2163,7 +2162,7 @@
}
if(!zoomstate_set)
- SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && !g_minstagib && self.weapon == WEP_NEX));
+ SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX));
float oldspectatee_status;
oldspectatee_status = self.spectatee_status;
Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_impulse.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_impulse.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_impulse.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -56,9 +56,50 @@
}
};
+/*
+ * Impulse map:
+ *
+ * 0 reserved (no input)
+ * 1 to 9: weapon shortcuts
+ * 10: next weapon
+ * 11: most recently used weapon
+ * 12: previous weapon
+ * 13: best weapon
+ * 17: throw weapon
+ *
+ * 30 to 39: create waypoints
+ * 47: clear personal waypoints
+ * 48: clear team waypoints
+ * 49: turn base waypoints on/off
+ *
+ * 99: loaded
+ *
+ * 140: moving clone
+ * 141: ctf speedrun
+ * 142: fixed clone
+ * 143: emergency teleport
+ * 144: printsurfaceinfo
+ * 145: distance
+ *
+ * TODO:
+ * 200 to 209: prev weapon shortcuts
+ * 210 to 219: best weapon shortcuts
+ * 220 to 229: next weapon shortcuts
+ * 230 to 253: individual weapons (up to 24)
+ */
+
void ImpulseCommands (void)
{
local float imp;
+ vector start, end, enddown;
+ float i;
+ float m;
+ float good, evil, evilsurf;
+ float maxattempts;
+ vector org, delta;
+ float wep;
+ entity e;
+
imp = self.impulse;
if (!imp || gameover)
return;
@@ -67,130 +108,178 @@
if (timeoutStatus == 2) //don't allow any impulses while the game is paused
return;
- if (imp >= 1 && imp <= 12)
+ if (imp >= 1 && imp <= 9)
{
// weapon switching impulses
if(self.deadflag == DEAD_NO)
+ W_NextWeaponOnImpulse(imp);
+ else
+ self.impulse = imp; // retry in next frame
+ }
+ else if(imp >= 10 && imp <= 17)
+ {
+ if(self.deadflag == DEAD_NO)
{
- if (imp <= 9)
- W_SwitchWeapon (imp);
- else if (imp == 10)
- W_NextWeapon ();
- else if (imp == 12)
- W_PreviousWeapon ();
- else if (imp == 11) // last weapon
- W_SwitchWeapon (self.cnt);
+ switch(imp)
+ {
+ case 10:
+ W_NextWeapon ();
+ break;
+ case 11:
+ W_SwitchWeapon (self.cnt); // previously used
+ break;
+ case 12:
+ W_PreviousWeapon ();
+ break;
+ case 13:
+ W_SwitchWeapon (w_getbestweapon(self));
+ break;
+ case 14:
+ W_NextWeaponOnImpulse(0);
+ break;
+ case 17:
+ if (!g_minstagib)
+ W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
+ break;
+ }
}
else
self.impulse = imp; // retry in next frame
}
- // throw weapon
- else if (imp == 17)
+ else if(imp >= 200 && imp <= 229)
{
if(self.deadflag == DEAD_NO)
- if (!g_minstagib)
- W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
+ {
+ // custom order weapon cycling
+ i = mod(imp, 10);
+ m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
+ W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
+ }
+ else
+ self.impulse = imp; // retry in next frame
}
+ else if(imp >= 230 && imp <= 253)
+ {
+ if(self.deadflag == DEAD_NO)
+ W_SwitchWeapon (imp - 230 + WEP_FIRST);
+ else
+ self.impulse = imp; // retry in next frame
+ }
// deploy waypoints
else if (imp >= 30 && imp <= 49)
{
- if(imp == 30)
+ switch(imp)
{
- WaypointSprite_DeployPersonal("waypoint", self.origin);
- self.personal_v_angle = self.v_angle;
- self.personal_velocity = self.velocity;
- sprint(self, "personal waypoint spawned at location\n");
+ case 30:
+ WaypointSprite_DeployPersonal("waypoint", self.origin);
+ self.personal_v_angle = self.v_angle;
+ self.personal_velocity = self.velocity;
+ sprint(self, "personal waypoint spawned at location\n");
+ break;
+ case 31:
+ WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
+ self.personal_v_angle = self.v_angle;
+ self.personal_velocity = '0 0 0';
+ sprint(self, "personal waypoint spawned at crosshair\n");
+ break;
+ case 32:
+ if(vlen(self.death_origin))
+ {
+ WaypointSprite_DeployPersonal("waypoint", self.death_origin);
+ self.personal_v_angle = self.v_angle;
+ self.personal_velocity = '0 0 0';
+ sprint(self, "personal waypoint spawned at death location\n");
+ }
+ break;
+ case 33:
+ if(self.deadflag == DEAD_NO && teams_matter)
+ {
+ WaypointSprite_Attach("helpme", TRUE);
+ sprint(self, "HELP ME attached\n");
+ }
+ break;
+ case 34:
+ WaypointSprite_DeployFixed("here", FALSE, self.origin);
+ sprint(self, "HERE spawned at location\n");
+ break;
+ case 35:
+ WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
+ sprint(self, "HERE spawned at crosshair\n");
+ break;
+ case 36:
+ if(vlen(self.death_origin))
+ {
+ WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
+ sprint(self, "HERE spawned at death location\n");
+ }
+ break;
+ case 37:
+ WaypointSprite_DeployFixed("danger", FALSE, self.origin);
+ sprint(self, "DANGER spawned at location\n");
+ break;
+ case 38:
+ WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
+ sprint(self, "DANGER spawned at crosshair\n");
+ break;
+ case 39:
+ if(vlen(self.death_origin))
+ {
+ WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
+ sprint(self, "DANGER spawned at death location\n");
+ }
+ break;
+ case 47:
+ WaypointSprite_ClearPersonal();
+ sprint(self, "personal waypoint cleared\n");
+ break;
+ case 48:
+ WaypointSprite_ClearOwned();
+ sprint(self, "all waypoints cleared\n");
+ break;
+ case 49:
+ self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
+ sprint(self, "fixed waypoints now ");
+ if(self.cvar_cl_hidewaypoints)
+ sprint(self, "OFF\n");
+ else
+ sprint(self, "ON\n");
+ break;
}
- else if(imp == 31)
- {
- WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
- self.personal_v_angle = self.v_angle;
- self.personal_velocity = '0 0 0';
- sprint(self, "personal waypoint spawned at crosshair\n");
- }
- else if(imp == 32 && vlen(self.death_origin))
- {
- WaypointSprite_DeployPersonal("waypoint", self.death_origin);
- self.personal_v_angle = self.v_angle;
- self.personal_velocity = '0 0 0';
- sprint(self, "personal waypoint spawned at death location\n");
- }
- else if(imp == 33 && self.deadflag == DEAD_NO && teams_matter)
- {
- WaypointSprite_Attach("helpme", TRUE);
- sprint(self, "HELP ME attached\n");
- }
- else if(imp == 34)
- {
- WaypointSprite_DeployFixed("here", FALSE, self.origin);
- sprint(self, "HERE spawned at location\n");
- }
- else if(imp == 35)
- {
- WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
- sprint(self, "HERE spawned at crosshair\n");
- }
- else if(imp == 36 && vlen(self.death_origin))
- {
- WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
- sprint(self, "HERE spawned at death location\n");
- }
- else if(imp == 37)
- {
- WaypointSprite_DeployFixed("danger", FALSE, self.origin);
- sprint(self, "DANGER spawned at location\n");
- }
- else if(imp == 38)
- {
- WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
- sprint(self, "DANGER spawned at crosshair\n");
- }
- else if(imp == 39 && vlen(self.death_origin))
- {
- WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
- sprint(self, "DANGER spawned at death location\n");
- }
- else if(imp == 47)
- {
- WaypointSprite_ClearPersonal();
- sprint(self, "personal waypoint cleared\n");
- }
- else if(imp == 48)
- {
- WaypointSprite_ClearOwned();
- sprint(self, "all waypoints cleared\n");
- }
- else if(imp == 49)
- {
- self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
- sprint(self, "fixed waypoints now ");
- if(self.cvar_cl_hidewaypoints)
- sprint(self, "OFF\n");
- else
- sprint(self, "ON\n");
- }
}
- else
+ else if(imp >= 140 && imp <= 149 || imp == 99) // 10 cheats ought to be enough for anyone
{
- if (sv_cheats)
+ if(sv_cheats)
+ if(self.deadflag == DEAD_NO)
{
- if(imp == 19)
+ switch(imp)
{
- makevectors(self.v_angle);
- traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
- if (trace_fraction < 1)
- printsurfaceinfo(trace_ent, trace_endpos);
- }
- else if(imp == 20)
- {
- makevectors(self.v_angle);
- traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
- sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
- }
- else if(self.deadflag == DEAD_NO)
- {
- if(imp == 77)
- {
+ case 99:
+ self.weapons |= WEPBIT_ALL;
+ self.ammo_shells = g_pickup_shells_max;
+ self.ammo_nails = g_pickup_nails_max;
+ self.ammo_rockets = g_pickup_rockets_max;
+ self.ammo_cells = g_pickup_cells_max;
+ self.health = g_pickup_healthsmall_max;
+ self.armorvalue = g_pickup_armorsmall_max;
+ self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
+ self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
+ self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
+ // precache weapon models/sounds
+ wep = WEP_FIRST;
+ while (wep <= WEP_LAST)
+ {
+ weapon_action(wep, WR_PRECACHE);
+ wep = wep + 1;
+ }
+ break;
+ case 140:
+ makevectors (self.v_angle);
+ self.velocity = self.velocity + v_forward * 300;
+ CopyBody(1);
+ self.lip += 1;
+ self.velocity = self.velocity - v_forward * 300;
+ break;
+ case 141:
if(self.waypointsprite_deployed_personal)
{
self.speedrunning = TRUE;
@@ -218,57 +307,21 @@
self.ammo_shells = 999;
self.health = start_health;
self.armorvalue = start_armorvalue;
- self.items |= itemsInMap & (IT_LASER | IT_SHOTGUN | IT_UZI | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
+ self.weapons |= weaponsInMap;
self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
}
+ else if(self.deadflag != DEAD_NO)
+ sprint(self, "UR DEAD AHAHAH))\n");
else
sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
- }
- else if(imp == 99)
- {
- self.items |= (IT_LASER | IT_UZI | IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER);
- self.ammo_shells = g_pickup_shells_max;
- self.ammo_nails = g_pickup_nails_max;
- self.ammo_rockets = g_pickup_rockets_max;
- self.ammo_cells = g_pickup_cells_max;
- self.health = g_pickup_healthsmall_max;
- self.armorvalue = g_pickup_armorsmall_max;
- self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
- self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
- self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
- // precache weapon models/sounds
- local float wep;
- wep = WEP_FIRST;
- while (wep <= WEP_LAST)
- {
- weapon_action(wep, WR_PRECACHE);
- wep = wep + 1;
- }
- }
- else if (imp == 13)
- {
- makevectors (self.v_angle);
- self.velocity = self.velocity + v_forward * 300;
- CopyBody(1);
- self.lip += 1;
- self.velocity = self.velocity - v_forward * 300;
- }
- else if (imp == 14)
- {
+ break;
+ case 142:
CopyBody(0);
self.lip += 1;
- }
- else if (imp == 143) // actually: impulse 911
- {
- vector start, end, enddown;
- float i;
- float m;
- float good, evil, evilsurf;
- float maxattempts;
- vector org, delta;
-
+ break;
+ case 143:
good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
evilsurf = Q3SURFACEFLAG_SKY;
@@ -362,18 +415,43 @@
sprint(self, "Emergency teleport could not find a good location, forget it!\n");
self.dphitcontentsmask = m;
- }
+ break;
+ case 144:
+ makevectors(self.v_angle);
+ traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
+ if (trace_fraction < 1)
+ printsurfaceinfo(trace_ent, trace_endpos);
+ break;
+ case 145:
+ makevectors(self.v_angle);
+ traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
+ sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
+ break;
}
}
}
-
- if (cvar("g_waypointeditor"))
+ else if(imp >= 103 && imp <= 106)
{
- local entity e;
- if (imp == 103) waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
- else if (imp == 104) {e = navigation_findnearestwaypoint(self, FALSE);if (e) waypoint_remove(e);}
- else if (imp == 105) waypoint_schedulerelinkall();
- else if (imp == 106) waypoint_saveall();
+ if(cvar("g_waypointeditor"))
+ {
+ switch(imp)
+ {
+ case 103:
+ waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
+ break;
+ case 104:
+ e = navigation_findnearestwaypoint(self, FALSE);
+ if (e)
+ waypoint_remove(e);
+ break;
+ case 105:
+ waypoint_schedulerelinkall();
+ break;
+ case 106:
+ waypoint_saveall();
+ break;
+ }
+ }
}
//TetrisImpulses(imp);
Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_player.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -413,7 +413,7 @@
else
player_setanim(self.anim_pain2, FALSE, TRUE, TRUE);
- if(deathtype != IT_LASER || attacker != self || self.health < 2 * cvar("g_balance_laser_primary_damage") * cvar("g_balance_selfdamagepercent") + 1)
+ if(deathtype != WEP_LASER || attacker != self || self.health < 2 * cvar("g_balance_laser_primary_damage") * cvar("g_balance_selfdamagepercent") + 1)
// exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
{
if(self.health > 75) // TODO make a "gentle" version?
@@ -504,6 +504,7 @@
kh_Key_DropAll(self, FALSE);
else
kh_Key_DropAll(self, TRUE);
+ Portal_ClearAll(self);
if(self.flagcarried)
DropFlag(self.flagcarried);
// clear waypoints
Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weapons.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,99 +1,233 @@
+// switch between weapons
+void W_SwitchWeapon(float imp)
+{
+ if (self.weapon != imp)
+ if (client_hasweapon(self, imp, TRUE, TRUE))
+ W_SwitchWeapon_Force(self, imp);
+};
+float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain)
+{
+ float n, i, weaponwant, first_valid, prev_valid, switchtonext, switchtolast;
+ n = tokenize(weaponorder);
+ switchtonext = switchtolast = 0;
+ first_valid = prev_valid = 0;
+
+ if(dir == 0)
+ switchtonext = 1;
+
+ for(i = 0; i < n; ++i)
+ {
+ weaponwant = stof(argv(i));
+
+ if(imp >= 0)
+ if((get_weaponinfo(weaponwant)).impulse != imp)
+ continue;
+
+ if(client_hasweapon(pl, weaponwant, TRUE, FALSE))
+ {
+ if(switchtonext)
+ return weaponwant;
+ if(!first_valid)
+ first_valid = weaponwant;
+ if(weaponwant == pl.switchweapon)
+ {
+ if(dir >= 0)
+ switchtonext = 1;
+ else if(prev_valid)
+ return prev_valid;
+ else
+ switchtolast = 1;
+ }
+ prev_valid = weaponwant;
+ }
+ }
+ if(first_valid)
+ {
+ if(switchtolast)
+ return prev_valid;
+ else
+ return first_valid;
+ }
+ // complain
+ if(complain)
+ {
+ for(i = 0; i < n; ++i)
+ {
+ weaponwant = stof(argv(i));
+ if(imp >= 0)
+ if((get_weaponinfo(weaponwant)).impulse != imp)
+ continue;
+ client_hasweapon(pl, weaponwant, TRUE, TRUE);
+ }
+ }
+ return 0;
+}
+
+void W_CycleWeapon(string weaponorder, float dir)
+{
+ float w;
+ w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1);
+ if(w > 0)
+ W_SwitchWeapon(w);
+}
+
+void W_NextWeaponOnImpulse(float imp)
+{
+ float w;
+ w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1);
+ if(w > 0)
+ W_SwitchWeapon(w);
+}
+
+// next weapon
+void W_NextWeapon()
+{
+ W_CycleWeapon(self.cvar_cl_weaponpriority, -1);
+}
+
+// prev weapon
+void W_PreviousWeapon()
+{
+ W_CycleWeapon(self.cvar_cl_weaponpriority, +1);
+}
+
+string W_FixWeaponOrder(string order, float complete)
+{
+ string neworder;
+ float i, n, w;
+
+ n = tokenize(order);
+ for(i = 0; i < n; ++i)
+ {
+ w = stof(argv(i));
+ if(w >= WEP_FIRST && w <= WEP_LAST && w == floor(w))
+ neworder = strcat(neworder, ftos(w), " ");
+ }
+
+ if(complete)
+ {
+ n = tokenize(neworder);
+ for(w = WEP_LAST; w >= WEP_FIRST; --w)
+ {
+ for(i = 0; i < n; ++i)
+ if(stof(argv(i)) == w)
+ break;
+ if(i == n) // not found
+ neworder = strcat(neworder, ftos(w), " ");
+ }
+ }
+
+ return substring(neworder, 0, strlen(neworder) - 1);
+}
+
+string W_FixWeaponOrder_AllowIncomplete(string order)
+{
+ return W_FixWeaponOrder(order, 0);
+}
+
+string W_FixWeaponOrder_ForceComplete(string order)
+{
+ if(order == "")
+ order = cvar_string("cl_weaponpriority");
+ return W_FixWeaponOrder(order, 1);
+}
+
+float w_getbestweapon(entity e)
+{
+ return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, 0);
+};
+
// generic weapons table
-// add new weapons here
+// TODO should they be macros instead?
float weapon_action(float wpn, float wrequest)
{
- if (wpn == WEP_LASER)
- return w_laser(wrequest);
- else if (wpn == WEP_SHOTGUN)
- return w_shotgun(wrequest);
- else if (wpn == WEP_UZI)
- return w_uzi(wrequest);
- else if (wpn == WEP_GRENADE_LAUNCHER)
- return w_glauncher(wrequest);
- else if (wpn == WEP_ELECTRO)
- return w_electro(wrequest);
- else if (wpn == WEP_CRYLINK)
- return w_crylink(wrequest);
- else if (wpn == WEP_NEX)
- return w_nex(wrequest);
- else if (wpn == WEP_HAGAR)
- return w_hagar(wrequest);
- else if (wpn == WEP_ROCKET_LAUNCHER)
- return w_rlauncher(wrequest);
- return FALSE;
+ return (get_weaponinfo(wpn)).weapon_func(wrequest);
};
string W_Name(float weaponid)
{
- if(weaponid == WEP_LASER) return "Laser";
- if(weaponid == WEP_UZI) return "Machine Gun";
- if(weaponid == WEP_SHOTGUN) return "Shotgun";
- if(weaponid == WEP_GRENADE_LAUNCHER) return "Mortar";
- if(weaponid == WEP_ELECTRO) return "Electro";
- if(weaponid == WEP_NEX) return "Nex";
- if(weaponid == WEP_HAGAR) return "Hagar";
- if(weaponid == WEP_ROCKET_LAUNCHER) return "Rocket Launcher";
- if(weaponid == WEP_CRYLINK) return "Crylink";
- return "@!#%'n Tuba";
+ return (get_weaponinfo(weaponid)).message;
}
-float W_ItemCode(float wpn)
+float W_WeaponBit(float wpn)
{
- switch(wpn)
- {
- case WEP_LASER: return IT_LASER;
- case WEP_SHOTGUN: return IT_SHOTGUN;
- case WEP_UZI: return IT_UZI;
- case WEP_GRENADE_LAUNCHER: return IT_GRENADE_LAUNCHER;
- case WEP_ELECTRO: return IT_ELECTRO;
- case WEP_CRYLINK: return IT_CRYLINK;
- case WEP_NEX: return IT_NEX;
- case WEP_HAGAR: return IT_HAGAR;
- case WEP_ROCKET_LAUNCHER: return IT_ROCKET_LAUNCHER;
- default: return 0;
- }
+ return (get_weaponinfo(wpn)).weapons;
}
float W_AmmoItemCode(float wpn)
{
- switch(wpn)
- {
- case WEP_SHOTGUN: return IT_SHELLS;
- case WEP_UZI: return IT_NAILS;
- case WEP_GRENADE_LAUNCHER: return IT_ROCKETS;
- case WEP_ELECTRO: return IT_CELLS;
- case WEP_CRYLINK: return IT_CELLS;
- case WEP_NEX: return IT_CELLS;
- case WEP_HAGAR: return IT_ROCKETS;
- case WEP_ROCKET_LAUNCHER: return IT_ROCKETS;
- default: return 0;
- }
+ return (get_weaponinfo(wpn)).items;
}
-// think function for tossed weapons
void thrown_wep_think()
{
self.solid = SOLID_TRIGGER;
self.owner = world;
SUB_SetFade(self, time + 20, 1);
- setorigin(self, self.origin);
-};
+}
+// returns amount of ammo used, or -1 for failure, or 0 for no ammo count
+float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
+{
+ entity oldself, wep;
+ float wa, ammo;
+ var .float ammofield;
+
+ wep = spawn();
+
+ setorigin(wep, org);
+ wep.classname = "droppedweapon";
+ wep.velocity = velo;
+ wep.owner = wep.enemy = own;
+ wep.classname = "droppedweapon";
+ wep.flags = wep.flags | FL_TOSSED;
+ wep.colormap = own.colormap;
+
+ wa = W_AmmoItemCode(wpn);
+ if(wa == IT_SUPERWEAPON || wa == 0)
+ {
+ oldself = self;
+ self = wep;
+ weapon_defaultspawnfunc(wpn);
+ self = oldself;
+ if(startitem_failed)
+ return -1;
+ wep.think = thrown_wep_think;
+ wep.nextthink = time + 0.5;
+ return 0;
+ }
+ else
+ {
+ ammofield = Item_CounterField(wa);
+ oldself = self;
+ self = wep;
+ weapon_defaultspawnfunc(wpn);
+ self = oldself;
+ if(startitem_failed)
+ return -1;
+ if(doreduce)
+ {
+ ammo = min(own.ammofield, wep.ammofield);
+ wep.ammofield = ammo;
+ own.ammofield -= ammo;
+ }
+ wep.think = thrown_wep_think;
+ wep.nextthink = time + 0.5;
+ return wep.ammofield;
+ }
+}
+
// toss current weapon
void W_ThrowWeapon(vector velo, vector delta, float doreduce)
{
- local float w, ammo;
- local entity wep, e;
- local .float ammofield;
+ local float w, a, wb;
w = self.weapon;
if (w == 0)
return; // just in case
if (w == WEP_LASER)
- return;
- if (g_instagib)
- return;
+ return; // just in case
if (g_rocketarena)
return;
if (g_lms)
@@ -103,120 +237,21 @@
if (!cvar("g_pickup_items"))
return;
- e = self;
- wep = spawn();
- self = wep;
-
- setorigin(wep, e.origin + delta);
- makevectors(e.angles);
- wep.classname = "droppedweapon";
- wep.velocity = velo; // e.velocity * 0.5 + v_forward * 750;
- SUB_SetFade(wep, time + 20, 1);
-
- ammofield = Item_CounterField(W_AmmoItemCode(w));
- w = W_ItemCode(w);
- if(!(e.items & w))
+ wb = W_WeaponBit(w);
+ self.weapons = self.weapons - (self.weapons & wb);
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
+ if(a < 0)
+ return;
+ if(self.health >= 1)
{
- remove(wep);
- goto leave;
+ if(a == 0)
+ sprint(self, strcat("You dropped the ^2", W_Name(w), "\n"));
+ else
+ sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", ftos(a), " ", Item_CounterFieldName(W_AmmoItemCode(w)), "\n"));
}
- Item_SpawnByItemCode(w);
- if(startitem_failed)
- goto leave;
- if(doreduce)
- {
- ammo = min(e.ammofield, wep.ammofield);
- wep.ammofield = ammo;
- e.ammofield -= ammo;
- }
-
- if(e.items & w)
- if(e.health >= 1)
- sprint(e, strcat("You dropped the ^2", wep.netname, " with ", ftos(wep.ammofield), " ammo", "\n"));
-
- wep.owner = e;
- setorigin(wep, wep.origin);
- wep.nextthink = time + 0.5;
- wep.think = thrown_wep_think;
- wep.classname = "droppedweapon";
- wep.flags = wep.flags | FL_TOSSED;
- e.items = e.items - (e.items & w);
- e.switchweapon = w_getbestweapon(e);
- wep.colormap = e.colormap;
- if (e.switchweapon != e.weapon)
- e.cnt = e.weapon;
-
-:leave
- self = e;
};
-// switch between weapons
-void W_SwitchWeapon(float imp)
-{
- if (self.weapon != imp)
- if (client_hasweapon(self, imp, TRUE, TRUE))
- {
- self.cnt = self.weapon ? self.weapon : self.switchweapon;
- self.switchweapon = imp;
- }
-};
-
-// next weapon
-void W_NextWeapon()
-{
- local float weaponwant, maxtries;
-
- maxtries = WEP_LAST;
-
- weaponwant = self.switchweapon + 1;
- if (weaponwant < WEP_FIRST)
- weaponwant = WEP_LAST;
- if (weaponwant > WEP_LAST)
- weaponwant = WEP_FIRST;
- while(!client_hasweapon(self, weaponwant, TRUE, FALSE))
- {
- if(!maxtries)
- return;
-
- maxtries -= 1;
- weaponwant = weaponwant + 1;
- if (weaponwant < WEP_FIRST)
- weaponwant = WEP_LAST;
- if (weaponwant > WEP_LAST)
- weaponwant = WEP_FIRST;
- }
- self.cnt = self.weapon ? self.weapon : self.switchweapon;
- self.switchweapon = weaponwant;
-};
-
-// prev weapon
-void W_PreviousWeapon()
-{
- local float weaponwant, maxtries;
-
- maxtries = WEP_LAST;
-
- weaponwant = self.switchweapon - 1;
- if (weaponwant < WEP_FIRST)
- weaponwant = WEP_LAST;
- if (weaponwant > WEP_LAST)
- weaponwant = WEP_FIRST;
- while(!client_hasweapon(self, weaponwant, TRUE, FALSE))
- {
- if(!maxtries)
- return;
-
- maxtries -= 1;
- weaponwant = weaponwant - 1;
- if (weaponwant < WEP_FIRST)
- weaponwant = WEP_LAST;
- if (weaponwant > WEP_LAST)
- weaponwant = WEP_FIRST;
- }
- self.cnt = self.weapon ? self.weapon : self.switchweapon;
- self.switchweapon = weaponwant;
-};
-
// Bringed back weapon frame
void W_WeaponFrame()
{
@@ -250,8 +285,8 @@
}
else if (self.weaponentity.state == WS_READY)
{
-#ifdef INDEPENDENT_ATTACK_FINISHED
- if(ATTACK_FINISHED(self) > time + frametime * 0.5)
+#ifndef INDEPENDENT_ATTACK_FINISHED
+ if(ATTACK_FINISHED(self) <= time + frametime * 0.5)
{
#endif
sound (self, CHAN_WEAPON, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
@@ -259,12 +294,15 @@
// set up weapon switch think in the future, and start drop anim
weapon_thinkf(WFRAME_IDLE, cvar("g_balance_weaponswitchdelay"), w_clear);
weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE);
-#ifdef INDEPENDENT_ATTACK_FINISHED
+#ifndef INDEPENDENT_ATTACK_FINISHED
}
#endif
}
}
+ float wb;
+ wb = W_WeaponBit(self.weapon);
+
// call the think code which may fire the weapon
// and do so multiple times to resolve framerate dependency issues if the
// server framerate is very low and the weapon fire rate very high
@@ -273,7 +311,13 @@
while (c < 5)
{
c = c + 1;
- weapon_action(self.weapon, WR_THINK);
+ if(wb && self.weapons & wb == 0)
+ {
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ wb = 0;
+ }
+ if(wb)
+ weapon_action(self.weapon, WR_THINK);
if (time + frametime * 0.5 >= self.weapon_nextthink)
self.weapon_think();
}
@@ -355,20 +399,20 @@
if(nixnex_nextchange != self.nixnex_lastchange_id) // this shall only be called once per round!
{
self.nixnex_lastchange_id = nixnex_nextchange;
- if (cvar("g_use_ammunition"))
+ if (self.items & IT_UNLIMITED_AMMO)
{
+ self.ammo_shells = cvar("g_pickup_shells_max");
+ self.ammo_nails = cvar("g_pickup_nails_max");
+ self.ammo_rockets = cvar("g_pickup_rockets_max");
+ self.ammo_cells = cvar("g_pickup_cells_max");
+ }
+ else
+ {
self.ammo_shells = cvar("g_balance_nixnex_ammo_shells");
self.ammo_nails = cvar("g_balance_nixnex_ammo_nails");
self.ammo_rockets = cvar("g_balance_nixnex_ammo_rockets");
self.ammo_cells = cvar("g_balance_nixnex_ammo_cells");
}
- else
- {
- self.ammo_shells = cvar("g_pickup_shells_max");
- self.ammo_nails = cvar("g_pickup_nails_max");
- self.ammo_rockets = cvar("g_pickup_rockets_max");
- self.ammo_cells = cvar("g_pickup_cells_max");
- }
self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
if(dt >= 1 && dt <= 5)
self.nixnex_lastinfotime = -42;
@@ -382,7 +426,7 @@
centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nixnex_nextweapon), "\n"));
}
- if(cvar("g_use_ammunition") && time > self.nixnex_nextincr)
+ if(!(self.items & IT_UNLIMITED_AMMO) && time > self.nixnex_nextincr)
{
self.ammo_shells = self.ammo_shells + cvar("g_balance_nixnex_ammoincr_shells");
self.ammo_nails = self.ammo_nails + cvar("g_balance_nixnex_ammoincr_nails");
@@ -391,10 +435,10 @@
self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
}
- self.items = self.items - (self.items & (IT_LASER | IT_SHOTGUN | IT_UZI | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER));
+ self.weapons = 0;
if(g_nixnex_with_laser)
- self.items = self.items | IT_LASER;
- self.items = self.items | W_ItemCode(nixnex_weapon);
+ self.weapons = self.weapons | WEPBIT_LASER;
+ self.weapons = self.weapons | W_WeaponBit(nixnex_weapon);
if(self.switchweapon != nixnex_weapon)
if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
@@ -403,3 +447,19 @@
}
}
+void RegisterWeapons()
+{
+ register_dummy_weapon();
+ // %weaponaddpoint
+ register_weapon(WEP_LASER, w_laser, 0, 1, 1, 0, "laser", "laser", "Laser");
+ register_weapon(WEP_SHOTGUN, w_shotgun, IT_SHELLS, 2, 1, 2500, "shotgun", "shotgun", "Shotgun");
+ register_weapon(WEP_UZI, w_uzi, IT_NAILS, 3, 1, 5000, "uzi", "uzi", "Machine Gun");
+ register_weapon(WEP_GRENADE_LAUNCHER, w_glauncher, IT_ROCKETS, 4, 1, 5000, "gl", "grenadelauncher", "Mortar");
+ register_weapon(WEP_ELECTRO, w_electro, IT_CELLS, 5, 1, 5000, "electro", "electro", "Electro");
+ register_weapon(WEP_CRYLINK, w_crylink, IT_CELLS, 6, 1, 5000, "crylink", "crylink", "Crylink");
+ register_weapon(WEP_NEX, w_nex, IT_CELLS, 7, 1, 10000, "nex", "nex", "Nex");
+ register_weapon(WEP_HAGAR, w_hagar, IT_ROCKETS, 8, 1, 5000, "hagar", "hagar", "Hagar");
+ register_weapon(WEP_ROCKET_LAUNCHER, w_rlauncher, IT_ROCKETS, 9, 1, 10000, "rl", "rocketlauncher", "Rocket Launcher");
+ register_weapon(WEP_PORTO, w_porto, IT_SUPERWEAPON, 0, 0, 0, "porto" , "porto", "Port-O-Launch");
+ register_weapon(WEP_MINSTANEX, w_minstanex, IT_CELLS, 7, 0, 10000, "minstanex", "minstanex", "MinstaNex");
+}
Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_weaponsystem.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -7,6 +7,12 @@
===========================================================================
*/
+void W_SwitchWeapon_Force(entity e, float w)
+{
+ e.cnt = e.weapon ? e.weapon : e.switchweapon;
+ e.switchweapon = w;
+}
+
.float antilag_debug;
// VorteX: static frame globals
@@ -324,7 +330,7 @@
float client_hasweapon(entity cl, float wpn, float andammo, float complain)
{
- local float itemcode, f;
+ local float weaponbit, f;
local entity oldself;
if (wpn < WEP_FIRST || wpn > WEP_LAST)
@@ -333,8 +339,8 @@
sprint(self, "Invalid weapon\n");
return FALSE;
}
- itemcode = W_ItemCode(wpn);
- if (cl.items & itemcode)
+ weaponbit = W_WeaponBit(wpn);
+ if (cl.weapons & weaponbit)
{
if (andammo)
{
@@ -346,7 +352,7 @@
if (!f)
{
if (complain)
- sprint(self, "You don't have any ammo for that weapon\n");
+ sprint(cl, strcat("You don't have any ammo for the ^2", W_Name(wpn), "\n"));
return FALSE;
}
}
@@ -356,10 +362,10 @@
{
// DRESK - 3/16/07
// Report Proper Weapon Status / Modified Weapon Ownership Message
- if(itemsInMap & itemcode)
- sprint(self, strcat("You do not have the ^2", W_Name(wpn), "\n") );
+ if(weaponsInMap & weaponbit)
+ sprint(cl, strcat("You do not have the ^2", W_Name(wpn), "\n") );
else
- sprint(self, strcat("The ^2", W_Name(wpn), "^7 is ^1NOT AVAILABLE^7 in this map\n") );
+ sprint(cl, strcat("The ^2", W_Name(wpn), "^7 is ^1NOT AVAILABLE^7 in this map\n") );
}
return FALSE;
};
@@ -384,41 +390,17 @@
weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
};
-// FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
-float w_getbestweapon(entity e)
-{
-// add new weapons here
- if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
- return WEP_ROCKET_LAUNCHER;
- else if (client_hasweapon(e, WEP_NEX, TRUE, FALSE))
- return WEP_NEX;
- else if (client_hasweapon(e, WEP_HAGAR, TRUE, FALSE))
- return WEP_HAGAR;
- else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE, FALSE))
- return WEP_GRENADE_LAUNCHER;
- else if (client_hasweapon(e, WEP_ELECTRO, TRUE, FALSE))
- return WEP_ELECTRO;
- else if (client_hasweapon(e, WEP_CRYLINK, TRUE, FALSE))
- return WEP_CRYLINK;
- else if (client_hasweapon(e, WEP_UZI, TRUE, FALSE))
- return WEP_UZI;
- else if (client_hasweapon(e, WEP_SHOTGUN, TRUE, FALSE))
- return WEP_SHOTGUN;
- else if (client_hasweapon(e, WEP_LASER, FALSE, FALSE))
- return WEP_LASER;
- else
- return 0;
-};
-
// Setup weapon for client (after this raise frame will be launched)
-void weapon_setup(float windex, string wname, float hudammo)
+void weapon_setup(float windex)
{
- self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
- self.items = self.items | hudammo;
+ entity e;
+ e = get_weaponinfo(windex);
+ self.items = self.items - (self.items & IT_AMMO);
+ self.items = self.items | e.items;
// the two weapon entities will notice this has changed and update their models
self.weapon = windex;
- self.weaponname = wname;
+ self.weaponname = e.mdl;
};
// perform weapon to attack (weaponstate and attack_finished check is here)
@@ -434,9 +416,7 @@
if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
{
- self.switchweapon = w_getbestweapon(self);
- if (self.switchweapon != self.weapon)
- self.cnt = self.weapon;
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
return FALSE;
}
@@ -603,27 +583,52 @@
missile.velocity = W_CalculateProjectileVelocity(missile.owner.velocity, missile.velocity);
}
-void weapon_register(float wepcode, float minammo)
+
+// WEAPON PLUGIN SYSTEM
+entity weapon_info[24];
+entity dummy_weapon_info;
+.float(float) weapon_func;
+void register_weapon(float id, float(float) func, float ammotype, float i, float normalweapon, float pickupbasevalue, string modelname, string shortname, string name)
{
- string s;
- float itemcode;
- s = strcat("register_bestweapon ", ftos(wepcode), " "); // char for bestweapon
- s = strcat(s, ftos(wepcode), " "); // impulse
- s = strcat(s, ftos(W_ItemCode(wepcode)), " "); // item code
- s = strcat(s, ftos(wepcode), " "); // self.weapon code
-
- // ammo stat
- itemcode = W_AmmoItemCode(wepcode);
- if(itemcode == IT_SHELLS)
- s = strcat(s, "6 ");
- else if(itemcode == IT_NAILS)
- s = strcat(s, "7 ");
- else if(itemcode == IT_ROCKETS)
- s = strcat(s, "8 ");
- else // if(itemcode == IT_CELLS)
- s = strcat(s, "9 ");
-
- s = strcat(s, ftos(minammo), "\n");
- //dprint(s);
- stuffcmd(self, s);
+ entity e;
+ weapon_info[id - 1] = e = spawn();
+ e.classname = "weapon_info";
+ e.weapon = id;
+ e.weapons = power2of(id - 1);
+ e.netname = shortname;
+ e.message = name;
+ e.items = ammotype;
+ e.weapon_func = func;
+ e.mdl = modelname;
+ e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
+ e.spawnflags = normalweapon;
+ e.impulse = i;
+ e.bot_pickupbasevalue = pickupbasevalue;
}
+float w_null(float dummy)
+{
+ return 0;
+}
+void register_dummy_weapon()
+{
+ dummy_weapon_info = spawn();
+ dummy_weapon_info.classname = "weapon_info";
+ dummy_weapon_info.weapon = 0;
+ dummy_weapon_info.weapons = 0;
+ dummy_weapon_info.netname = "@!#%'n Tuba";
+ dummy_weapon_info.items = 0;
+ dummy_weapon_info.weapon_func = w_null;
+ dummy_weapon_info.mdl = "";
+ dummy_weapon_info.model = "";
+ dummy_weapon_info.spawnflags = 0;
+ dummy_weapon_info.impulse = -1;
+ dummy_weapon_info.bot_pickupbasevalue = 0;
+}
+entity get_weaponinfo(float id)
+{
+ entity w;
+ w = weapon_info[id - 1];
+ if(w)
+ return w;
+ return dummy_weapon_info;
+}
Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -265,7 +265,8 @@
} else if(argv(0) == "ready") {
if not(self.flags & FL_CLIENT)
return;
- if(cvar("sv_ready_restart"))
+ if((g_tourney && 0 < g_tourney_warmup_limit) // with unlimited warmup players have to be able to restart
+ || cvar("sv_ready_restart"))
{
if(timeoutStatus) {
return sprint(self, "^1You cannot reset the game while a timeout is active!\n");
@@ -401,7 +402,8 @@
if(g_tourney) {
tourneyInMatchStage = 1; //once the game is restarted the game is in match stage
//reset weapons and ammo, health and armor to default:
- start_items = IT_LASER | IT_SHOTGUN;
+ // TODO is this really the right way?!? see miscfunction.qc readlevelcvars()
+ start_weapons = WEPBIT_LASER | WEPBIT_SHOTGUN;
start_switchweapon = WEP_SHOTGUN;
start_ammo_shells = cvar("g_start_ammo_shells");
start_ammo_nails = cvar("g_start_ammo_nails");
@@ -413,11 +415,11 @@
restart_countdown = time + RESTART_COUNTDOWN;
restart_mapalreadyrestarted = 0; //reset this var, needed when cvar sv_ready_restart_repeatable is in use
//reset the .ready status of all players (also spectators)
- FOR_EACH_CLIENT(e)
+ FOR_EACH_CLIENTSLOT(e)
{
e.ready = 0;
}
- if(0<cvar("timelimit") || (g_tourney && cvar("g_tourney_warmup_unlimited_time")) )
+ if(0<cvar("timelimit") || (g_tourney && (-1 == g_tourney_warmup_limit)) )
{
// remember original timelimit on first restart
if(!timelimit_orig)
@@ -472,6 +474,8 @@
local entity e;
local float r, p;
+ r = p = 0;
+
FOR_EACH_REALPLAYER(e)
{
p += 1;
Modified: branches/nexuiz-2.0/data/qcsrc/server/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/constants.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/constants.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -154,43 +154,6 @@
float DEATH_MIRRORDAMAGE = 10014;
float DEATH_TURRET = 10100;
-
-
-
-float IT_LASER = 4096;
-float IT_SHOTGUN = 1;
-float IT_UZI = 2;
-float IT_GRENADE_LAUNCHER = 4;
-float IT_ELECTRO = 8;
-float IT_CRYLINK = 16;
-float IT_NEX = 32;
-float IT_HAGAR = 64;
-float IT_ROCKET_LAUNCHER = 128;
-
-float IT_SHELLS = 256;
-float IT_NAILS = 512;
-float IT_ROCKETS = 1024;
-float IT_CELLS = 2048;
-
-float IT_STRENGTH = 8192;
-float IT_INVINCIBLE = 16384;
-float IT_HEALTH = 32768;
-
-float IT_KEY1 = 131072;
-float IT_KEY2 = 262144;
-
-float IT_RED_FLAG_TAKEN = 32768;
-float IT_RED_FLAG_LOST = 65536;
-float IT_RED_FLAG_CARRING = 98304;
-float IT_BLUE_FLAG_TAKEN = 131072;
-float IT_BLUE_FLAG_LOST = 262144;
-float IT_BLUE_FLAG_CARRING = 393216;
-
-float IT_5HP = 524288;
-float IT_25HP = 1048576;
-float IT_ARMOR_SHARD = 2097152;
-float IT_ARMOR = 4194304;
-
vector PL_VIEW_OFS = '0 0 35';
vector PL_MIN = '-16 -16 -24';
vector PL_MAX = '16 16 45';
Modified: branches/nexuiz-2.0/data/qcsrc/server/defs.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/defs.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/defs.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -17,11 +17,16 @@
// Globals
float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_lms, g_runematch, g_race;
-float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_instagib, g_laserguided_missile, g_midair, g_minstagib, g_nixnex, g_nixnex_with_laser, g_norecoil, g_rocketarena, g_vampire, g_minstagib_invis_alpha;
+float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_nixnex, g_nixnex_with_laser, g_norecoil, g_rocketarena, g_vampire, g_minstagib_invis_alpha;
float g_tourney;
+float g_tourney_warmup_limit;
float g_ctf_win_mode;
float g_race_qualifying;
float tourneyInMatchStage;
+float g_pickup_respawntime_short;
+float g_pickup_respawntime_medium;
+float g_pickup_respawntime_long;
+float g_pickup_respawntime_powerup;
float sv_cheats;
float sv_gentle;
@@ -196,29 +201,19 @@
float WS_READY = 4; // idle frame
// weapon requests
-float WR_SETUP = 1; // setup weapon data
-float WR_THINK = 2; // logic to run every frame
-float WR_CHECKAMMO1 = 3; // checks ammo for weapon
-float WR_CHECKAMMO2 = 4; // checks ammo for weapon
-float WR_AIM = 5; // runs bot aiming code for this weapon
-float WR_PRECACHE = 6; // precaches models/sounds used by this weapon
-float WR_REGISTER = 7; // send data about the weapon to the client self (for ClientConnect)
+float WR_SETUP = 1; // setup weapon data
+float WR_THINK = 2; // logic to run every frame
+float WR_CHECKAMMO1 = 3; // checks ammo for weapon
+float WR_CHECKAMMO2 = 4; // checks ammo for weapon
+float WR_AIM = 5; // runs bot aiming code for this weapon
+float WR_PRECACHE = 6; // precaches models/sounds used by this weapon
+float WR_SUICIDEMESSAGE = 7; // sets w_deathtypestring or leaves it alone
+float WR_KILLMESSAGE = 8; // sets w_deathtypestring or leaves it alone
-// Weapon indexes
-float WEP_LASER = 1; // float IT_LASER = 4096;
-float WEP_SHOTGUN = 2; // float IT_SHOTGUN = 1;
-float WEP_UZI = 3; // float IT_UZI = 2;
-float WEP_GRENADE_LAUNCHER = 4; // float IT_GRENADE_LAUNCHER = 4;
-float WEP_ELECTRO = 5; // float IT_ELECTRO = 8;
-float WEP_CRYLINK = 6; // float IT_CRYLINK = 16;
-float WEP_NEX = 7; // float IT_NEX = 32;
-float WEP_HAGAR = 8; // float IT_HAGAR = 64;
-float WEP_ROCKET_LAUNCHER = 9; // float IT_ROCKET_LAUNCHER = 128;
-// For weapon cycling commands
-float WEP_FIRST = 1;
-float WEP_LAST = 9;
-float WEP_COUNT = 10;
+void weapon_defaultspawnfunc(float wpn);
+string w_deathtypestring;
+
void(entity client, string s) centerprint_builtin = #73;
.vector dest1, dest2;
@@ -340,14 +335,14 @@
.float() customizeentityforclient;
.float cvar_cl_handicap;
-.float cvar_cl_zoomfactor;
-.float cvar_cl_zoomspeed;
.float cvar_cl_playerdetailreduction;
.float cvar_cl_nogibs;
.float cvar_scr_centertime;
.float cvar_cl_shownames;
.float cvar_cl_hidewaypoints;
.string cvar_g_nexuizversion;
+.string cvar_cl_weaponpriority;
+.string cvar_cl_weaponpriorities[10];
.float version_nagtime;
@@ -372,11 +367,9 @@
typedef .float floatfield;
floatfield Item_CounterField(float it);
-float Item_WeaponCode(float it);
-void Item_SpawnByItemCode(float it);
float W_AmmoItemCode(float wpn);
-float W_ItemCode(float wpn);
+float W_WeaponBit(float wpn);
string W_Name(float weaponid);
void UpdateSelectedPlayer();
@@ -391,7 +384,7 @@
void FixIntermissionClient(entity e);
void FixClientCvars(entity e);
-float itemsInMap;
+float weaponsInMap;
void centerprint_atprio(entity e, float prio, string s);
void centerprint_expire(entity e, float prio);
@@ -494,3 +487,4 @@
string clientstuff;
.float stat_sys_ticrate;
.float phase;
+.float weapons;
Modified: branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_damage.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -105,7 +105,7 @@
// w = player.switchweapon;
if(w == 0)
w = player.cnt; // previous weapon!
- s = strcat(s, ftos(W_ItemCode(w)));
+ s = strcat(s, ftos(w));
if(time < player.strength_finished)
s = strcat(s, "S");
if(time < player.invincible_finished)
@@ -143,6 +143,7 @@
void Obituary (entity attacker, entity targ, float deathtype)
{
string s, a;
+ float p;
if (targ.classname == "player" || targ.classname == "corpse")
{
@@ -202,13 +203,12 @@
if (targ.killcount > 2)
bprint ("^1",s,"^1 ended it all with a ",ftos(targ.killcount)," scoring spree\n");
} else {
-
- if (deathtype == IT_GRENADE_LAUNCHER)
- bprint ("^1",s, "^1 detonated\n");
- else if (deathtype == IT_ELECTRO)
- bprint ("^1",s, "^1 played with plasma\n");
- else if (deathtype == IT_ROCKET_LAUNCHER)
- bprint ("^1",s, "^1 exploded\n");
+ if(deathtype >= WEP_FIRST && deathtype <= WEP_LAST)
+ {
+ w_deathtypestring = "couldn't resist the urge to self-destruct";
+ weapon_action(deathtype, WR_SUICIDEMESSAGE);
+ bprint("^1", s, "^1 ", w_deathtypestring, "\n");
+ }
else if (deathtype == DEATH_KILL)
bprint ("^1",s, "^1 couldn't take it anymore\n");
else if (deathtype == DEATH_ROT)
@@ -283,24 +283,16 @@
if(sv_gentle) {
bprint ("^1",s, "^1 needs a restart thanks to ", a, "\n");
} else {
- if (deathtype == IT_LASER)
- bprint ("^1",s, "^1 was blasted by ", a, "\n");
- else if (deathtype == IT_UZI)
- bprint ("^1",s, "^1 was riddled full of holes by ", a, "\n");
- else if (deathtype == IT_SHOTGUN)
- bprint ("^1",s, "^1 was gunned by ", a, "\n");
- else if (deathtype == IT_GRENADE_LAUNCHER)
- bprint ("^1", s, "^1 was blasted by ", a, "\n");
- else if (deathtype == IT_ELECTRO)
- bprint ("^1",s, "^1 was blasted by ", a, "\n");
- else if (deathtype == IT_CRYLINK)
- bprint ("^1",s, "^1 was blasted by ", a, "\n");
- else if (deathtype == IT_NEX)
- bprint ("^1",s, "^1 has been vaporized by ", a, "\n");
- else if (deathtype == IT_HAGAR)
- bprint ("^1",s, "^1 was pummeled by ", a, "\n");
- else if (deathtype == IT_ROCKET_LAUNCHER)
- bprint ("^1",s, "^1 was blasted by ", a, "\n");
+ if(deathtype >= WEP_FIRST && deathtype <= WEP_LAST)
+ {
+ w_deathtypestring = "was blasted by";
+ weapon_action(deathtype, WR_KILLMESSAGE);
+ p = strstrofs(w_deathtypestring, "#", 0);
+ if(p < 0)
+ bprint("^1", s, "^1 ", w_deathtypestring, " ", a, "\n");
+ else
+ bprint("^1", s, "^1 ", substring(w_deathtypestring, 0, p), a, "^1", substring(w_deathtypestring, p+1, strlen(w_deathtypestring) - (p+1)), "\n");
+ }
else if (deathtype == DEATH_TELEFRAG)
bprint ("^1",s, "^1 was telefragged by ", a, "\n");
else if (deathtype == DEATH_DROWN)
@@ -572,20 +564,20 @@
(deathtype == DEATH_SLIME) ||
(deathtype == DEATH_LAVA))
return;
- if (targ.armorvalue && (deathtype == IT_NEX) && damage)
+ if (targ.armorvalue && (deathtype == WEP_MINSTANEX) && damage)
{
targ.armorvalue -= 1;
centerprint(targ, strcat("^3Remaining extra lives: ",ftos(targ.armorvalue),"\n"));
damage = 0;
targ.hitsound += 1;
}
- else if (deathtype == IT_NEX && targ.items & IT_STRENGTH)
+ else if (deathtype == WEP_MINSTANEX && targ.items & IT_STRENGTH)
{
if(clienttype(attacker) == CLIENTTYPE_REAL)
if(IsDifferentTeam(targ, attacker))
yoda = 1;
}
- if (deathtype == IT_LASER)
+ if (deathtype == WEP_LASER)
{
damage = 0;
if (targ != attacker)
@@ -671,7 +663,6 @@
// Savage: vampire mode
if (g_vampire)
if (!g_minstagib)
- if (!g_instagib)
if (time > self.spawnshieldtime)
{
attacker.health += damage;
Modified: branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_hook.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -130,6 +130,7 @@
makevectors(self.owner.v_angle);
org = self.owner.origin + self.owner.view_ofs + v_forward * 8 - v_right * 8 + v_up * -12;
+#if 0
tracebox(org, self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self.owner);
// do not hit players with this, as they tend to get in the way just too often
// NOTE: this assumes sky brushes cannot get in the way
@@ -152,6 +153,7 @@
if(trace_ent.movetype != MOVETYPE_NONE)
SetMovetypeFollow(self, trace_ent);
}
+#endif
if(self.rope_length < 0)
self.rope_length = vlen(org - self.origin);
Modified: branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_triggers.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -469,16 +469,34 @@
}
-void target_speaker_use() {sound(self, CHAN_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);}
+// TODO add a way to do looped sounds with sound(); then complete this entity
+.float volume, atten;
+void target_speaker_use() {sound(self, CHAN_TRIGGER, self.noise, VOL_BASE * self.volume, self.atten);}
void spawnfunc_target_speaker()
{
if(self.noise)
precache_sound (self.noise);
IFTARGETED
+ {
+ if(!self.atten)
+ self.atten = ATTN_NORM;
+ else if(self.atten < 0)
+ self.atten = 0;
+ if(!self.volume)
+ self.volume = 1;
self.use = target_speaker_use;
+ }
else
- ambientsound (self.origin, self.noise, VOL_BASE, ATTN_STATIC);
+ {
+ if(!self.atten)
+ self.atten = ATTN_STATIC;
+ else if(self.atten < 0)
+ self.atten = 0;
+ if(!self.volume)
+ self.volume = 1;
+ ambientsound (self.origin, self.noise, VOL_BASE * self.volume, self.atten);
+ }
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/g_world.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/g_world.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/g_world.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -157,6 +157,7 @@
}
float world_already_spawned;
+void RegisterWeapons();
void spawnfunc_worldspawn (void)
{
float fd, l;
@@ -179,6 +180,9 @@
head = nextent(head);
}
+ // needs to be done so early as they would still spawn
+ RegisterWeapons();
+
if(GotoFirstMap())
return;
@@ -312,7 +316,7 @@
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), 1);
//if tourney is used map starts in warmup mode. if this mode shall stay unlimited, reset timelimit, but save the original one
- if(g_tourney && cvar("g_tourney_warmup_unlimited_time")) {
+ if(g_tourney && (-1 == g_tourney_warmup_limit)) {
timelimit_orig = cvar("timelimit");
cvar_set("timelimit", "0");
}
@@ -353,6 +357,8 @@
}
addstat(STAT_SYS_TICRATE, AS_FLOAT, stat_sys_ticrate);
+ addstat(STAT_WEAPONS, AS_INT, weapons);
+ addstat(STAT_SWITCHWEAPON, AS_INT, switchweapon);
next_pingtime = time + 5;
world_initialized = 1;
Modified: branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/havocbot.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -340,6 +340,7 @@
local float uzi ; uzi =-1000;
local float shotgun ; shotgun =-1000;
local float laser ; laser =-1000;
+ local float minstanex ; minstanex =-1000;
local float currentscore;
local float bestscore; bestscore = 0;
local float bestweapon; bestweapon=self.switchweapon;
@@ -354,6 +355,10 @@
// *(Time to get to target * weapon specfic hitchange bonus) / (in a time of maxdelaytime)
// *(Spread change of hit) // if it applies
// *(Penality for target beeing in air)
+ // %weaponaddpoint
+ if (client_hasweapon(self, WEP_MINSTANEX, TRUE, FALSE))
+ minstanex = (1000/cvar("g_balance_minstanex_refire")*1.0)
+ * (0.5);
if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
rocket = (cvar("g_balance_rocketlauncher_damage")/cvar("g_balance_rocketlauncher_refire")*0.75)
* bound(0,(cvar("g_balance_rocketlauncher_speed")/distance*maxdelaytime),1)*1.5;
@@ -400,15 +405,16 @@
dprint("Laser :", ftos(laser ), "\n\n");
*/
currentscore = -1;
- w = WEP_ROCKET_LAUNCHER ;s = rocket ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_NEX ;s = nex ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_HAGAR ;s = hagar ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_GRENADE_LAUNCHER ;s = grenade;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_ELECTRO ;s = electro;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_CRYLINK ;s = crylink;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_UZI ;s = uzi ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_SHOTGUN ;s = shotgun;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
- w = WEP_LASER ;s = laser ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_MINSTANEX ;s = minstanex;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_ROCKET_LAUNCHER ;s = rocket ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_NEX ;s = nex ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_HAGAR ;s = hagar ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_GRENADE_LAUNCHER ;s = grenade ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_ELECTRO ;s = electro ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_CRYLINK ;s = crylink ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_UZI ;s = uzi ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_SHOTGUN ;s = shotgun ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_LASER ;s = laser ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
// switch if the best weapon would provide a significant damage increase
if (bestscore > currentscore*1.5)
Modified: branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/miscfunctions.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -73,21 +73,18 @@
}
}
-void move_out_of_solid(entity e)
+float move_out_of_solid(entity e)
{
vector o, m0, m1;
o = e.origin;
traceline(o, o, MOVE_WORLDONLY, e);
if(trace_startsolid)
- {
- dprint("origin is in solid too! (", vtos(o), ")");
- return;
- }
+ return 0;
tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
if(!trace_startsolid)
- return;
+ return 1;
m0 = e.mins;
m1 = e.maxs;
@@ -104,9 +101,11 @@
tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
if(trace_startsolid)
{
- dprint("could not get out of solid (", vtos(o), ")\n");
- return;
+ setorigin(e, o);
+ return 0;
}
+
+ return 1;
}
string STR_PLAYER = "player";
@@ -202,7 +201,8 @@
o = self.origin;
self.mins = PL_MIN;
self.maxs = PL_MAX;
- move_out_of_solid(self);
+ if(!move_out_of_solid(self))
+ objerror("could not get out of solid at all!");
print("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
print(" needs to be moved out of solid, e.g. by '", ftos(self.origin_x - o_x));
print(" ", ftos(self.origin_y - o_y));
@@ -489,6 +489,21 @@
else
stuffcmd(self, strcat("sendcvar ", name, "\n"));
}
+void GetCvars_handleString_Fixup(float f, .string field, string name, string(string) func)
+{
+ GetCvars_handleString(f, field, name);
+ if(f >= 0) // also initialize to the fitting value for "" when sending cvars out
+ if(argv(f) == name)
+ {
+ string s;
+ s = func(strcat1(self.field));
+ if(s != self.field)
+ {
+ strunzone(self.field);
+ self.field = strzone(s);
+ }
+ }
+}
void GetCvars_handleFloat(float f, .float field, string name)
{
if(f < 0)
@@ -502,18 +517,29 @@
else
stuffcmd(self, strcat("sendcvar ", name, "\n"));
}
+string W_FixWeaponOrder_ForceComplete(string s);
+string W_FixWeaponOrder_AllowIncomplete(string s);
void GetCvars(float f)
{
GetCvars_handleFloat(f, autoswitch, "cl_autoswitch");
GetCvars_handleFloat(f, cvar_cl_hidewaypoints, "cl_hidewaypoints");
- GetCvars_handleFloat(f, cvar_cl_zoomfactor, "cl_zoomfactor");
- GetCvars_handleFloat(f, cvar_cl_zoomspeed, "cl_zoomspeed");
GetCvars_handleFloat(f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
GetCvars_handleFloat(f, cvar_cl_nogibs, "cl_nogibs");
GetCvars_handleFloat(f, cvar_scr_centertime, "scr_centertime");
GetCvars_handleFloat(f, cvar_cl_shownames, "cl_shownames");
GetCvars_handleString(f, cvar_g_nexuizversion, "g_nexuizversion");
GetCvars_handleFloat(f, cvar_cl_handicap, "cl_handicap");
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[1], "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[2], "cl_weaponpriority2", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[3], "cl_weaponpriority3", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[4], "cl_weaponpriority4", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[5], "cl_weaponpriority5", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[6], "cl_weaponpriority6", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleString_Fixup(f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
}
float fexists(string f)
@@ -674,6 +700,7 @@
float g_pickup_healthmega;
float g_pickup_healthmega_max;
+float start_weapons;
float start_items;
float start_switchweapon;
float start_ammo_shells;
@@ -683,8 +710,13 @@
float start_health;
float start_armorvalue;
+entity get_weaponinfo(float w);
+
void readlevelcvars(void)
{
+ entity e;
+ float i;
+
sv_cheats = cvar("sv_cheats");
sv_gentle = cvar("sv_gentle");
sv_foginterval = cvar("sv_foginterval");
@@ -692,7 +724,6 @@
g_jump_grunt = cvar("g_jump_grunt");
g_footsteps = cvar("g_footsteps");
g_grappling_hook = cvar("g_grappling_hook");
- g_instagib = cvar("g_instagib");
g_laserguided_missile = cvar("g_laserguided_missile");
g_midair = cvar("g_midair");
g_minstagib = cvar("g_minstagib");
@@ -702,12 +733,17 @@
g_rocketarena = cvar("g_rocketarena");
g_vampire = cvar("g_vampire");
g_tourney = cvar("g_tourney");
+ g_tourney_warmup_limit = cvar("g_tourney_warmup_limit");
sv_maxidle = cvar("sv_maxidle");
sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
sv_pogostick = cvar("sv_pogostick");
sv_doublejump = cvar("sv_doublejump");
- if(g_instagib) g_minstagib = g_nixnex = g_rocketarena = 0;
+ g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
+ g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
+ g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
+ g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
+
if(g_minstagib) g_nixnex = g_rocketarena = 0;
if(g_nixnex) g_rocketarena = 0;
@@ -735,6 +771,7 @@
g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
// initialize starting values for players
+ start_weapons = 0;
start_items = 0;
start_switchweapon = 0;
start_ammo_shells = 0;
@@ -744,31 +781,25 @@
start_health = cvar("g_balance_health_start");
start_armorvalue = cvar("g_balance_armor_start");
- if(g_instagib)
+ if(g_rocketarena)
{
- start_items = IT_NEX;
- start_switchweapon = WEP_NEX;
- weapon_action(start_switchweapon, WR_PRECACHE);
- start_ammo_cells = 999;
- }
- else if(g_rocketarena)
- {
- start_items = IT_ROCKET_LAUNCHER;
+ start_weapons = WEPBIT_ROCKET_LAUNCHER;
start_switchweapon = WEP_ROCKET_LAUNCHER;
weapon_action(start_switchweapon, WR_PRECACHE);
start_ammo_rockets = 999;
+ start_items |= IT_UNLIMITED_AMMO;
}
else if(g_nixnex)
{
- start_items = 0;
+ start_weapons = 0;
// will be done later
}
else if(g_minstagib)
{
start_health = 100;
start_armorvalue = 0;
- start_items = IT_NEX;
- start_switchweapon = WEP_NEX;
+ start_weapons = WEPBIT_MINSTANEX;
+ start_switchweapon = WEP_MINSTANEX;
weapon_action(start_switchweapon, WR_PRECACHE);
start_ammo_cells = cvar("g_minstagib_ammo_start");
g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
@@ -802,62 +833,21 @@
start_ammo_nails = cvar("g_pickup_nails_max");
start_ammo_rockets = cvar("g_pickup_rockets_max");
start_ammo_cells = cvar("g_pickup_cells_max");
+ start_items |= IT_UNLIMITED_AMMO;
}
- if (cvar("g_start_weapon_laser") || g_lms)
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
- start_items = start_items | IT_LASER;
- start_switchweapon = WEP_LASER;
- weapon_action(start_switchweapon, WR_PRECACHE);
+ e = get_weaponinfo(i);
+ if(!(e.weapon))
+ continue;
+ if(((e.spawnflags & 1) && (g_lms || g_tourney)) || cvar(strcat("g_start_weapon_", e.netname)))
+ {
+ start_weapons |= e.weapons;
+ start_switchweapon = e.weapon;
+ weapon_action(e.weapon, WR_PRECACHE);
+ }
}
- if (cvar("g_start_weapon_shotgun") || g_lms)
- {
- start_items = start_items | IT_SHOTGUN;
- start_switchweapon = WEP_SHOTGUN;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_uzi") || g_lms || g_tourney)
- {
- start_items = start_items | IT_UZI;
- start_switchweapon = WEP_UZI;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_grenadelauncher") || g_lms || g_tourney)
- {
- start_items = start_items | IT_GRENADE_LAUNCHER;
- start_switchweapon = WEP_GRENADE_LAUNCHER;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_electro") || g_lms || g_tourney)
- {
- start_items = start_items | IT_ELECTRO;
- start_switchweapon = WEP_ELECTRO;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_crylink") || g_lms || g_tourney)
- {
- start_items = start_items | IT_CRYLINK;
- start_switchweapon = WEP_CRYLINK;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_nex") || g_lms || g_tourney)
- {
- start_items = start_items | IT_NEX;
- start_switchweapon = WEP_NEX;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_hagar") || g_lms || g_tourney)
- {
- start_items = start_items | IT_HAGAR;
- start_switchweapon = WEP_HAGAR;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
- if (cvar("g_start_weapon_rocketlauncher") || g_lms || g_tourney)
- {
- start_items = start_items | IT_ROCKET_LAUNCHER;
- start_switchweapon = WEP_ROCKET_LAUNCHER;
- weapon_action(start_switchweapon, WR_PRECACHE);
- }
}
}
@@ -1238,3 +1228,176 @@
.float nottargeted;
#define IFTARGETED if(!self.nottargeted && self.targetname != "")
+
+float power2of(float e)
+{
+ return pow(2, e);
+}
+float log2of(float x)
+{
+ // NOTE: generated code
+ if(x > 2048)
+ if(x > 131072)
+ if(x > 1048576)
+ if(x > 4194304)
+ return 23;
+ else
+ if(x > 2097152)
+ return 22;
+ else
+ return 21;
+ else
+ if(x > 524288)
+ return 20;
+ else
+ if(x > 262144)
+ return 19;
+ else
+ return 18;
+ else
+ if(x > 16384)
+ if(x > 65536)
+ return 17;
+ else
+ if(x > 32768)
+ return 16;
+ else
+ return 15;
+ else
+ if(x > 8192)
+ return 14;
+ else
+ if(x > 4096)
+ return 13;
+ else
+ return 12;
+ else
+ if(x > 32)
+ if(x > 256)
+ if(x > 1024)
+ return 11;
+ else
+ if(x > 512)
+ return 10;
+ else
+ return 9;
+ else
+ if(x > 128)
+ return 8;
+ else
+ if(x > 64)
+ return 7;
+ else
+ return 6;
+ else
+ if(x > 4)
+ if(x > 16)
+ return 5;
+ else
+ if(x > 8)
+ return 4;
+ else
+ return 3;
+ else
+ if(x > 2)
+ return 2;
+ else
+ if(x > 1)
+ return 1;
+ else
+ return 0;
+}
+
+//
+// func_breakable
+// - basically func_assault_destructible for general gameplay use
+//
+float () crandom;
+void () SUB_UseTargets, assault_destructible_use, SUB_Remove, SUB_Null;
+void LaunchDebris (string debrisname) =
+{
+ local entity dbr;
+
+ if (debrisname == "" || !debrisname)
+ return;
+
+ dbr = spawn();
+ dbr.origin = self.origin;
+ setmodel (dbr, debrisname );
+ setsize (dbr, '0 0 0', '0 0 0');
+ dbr.velocity_x = 70 * crandom();
+ dbr.velocity_y = 70 * crandom();
+ dbr.velocity_z = 140 + 70 * random();
+ dbr.movetype = MOVETYPE_BOUNCE;
+ dbr.solid = SOLID_BBOX;
+ dbr.avelocity_x = random()*600;
+ dbr.avelocity_y = random()*600;
+ dbr.avelocity_z = random()*600;
+ dbr.think = SUB_Remove;
+ dbr.nextthink = time + 13 + random()*10;
+};
+
+.string debris1, debris2, debris3;
+.string mdl_dead;
+void func_breakable_destroy() {
+ if (self.mdl_dead)
+ setmodel(self, self.mdl_dead);
+ else {
+ self.model = "";
+ self.solid = SOLID_NOT;
+ }
+ self.takedamage = DAMAGE_NO;
+
+ // now throw around the debris
+ LaunchDebris(self.debris1);
+ LaunchDebris(self.debris2);
+ LaunchDebris(self.debris3);
+
+ SUB_UseTargets();
+
+ self.event_damage = SUB_Null;
+}
+
+void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) {
+
+ if(self.cnt > 0) {
+ self.health = self.health - damage;
+ // add pain effects?
+ }
+
+ if(self.health < 0) {
+ activator = attacker;
+ func_breakable_destroy();
+ }
+}
+
+// destructible walls that can be used to trigger target_objective_decrease
+void spawnfunc_func_breakable() {
+ if(!self.health)
+ self.health = 100;
+
+ self.max_health = self.health;
+
+ //self.cnt = 0; // not yet activated
+
+
+
+ self.classname = "func_breakable";
+ self.mdl = self.model;
+ setmodel(self, self.mdl);
+
+ self.solid = SOLID_BSP;
+
+ // precache all the models
+ if (self.mdl_dead)
+ precache_model(self.mdl_dead);
+ if (self.debris1)
+ precache_model(self.debris1);
+ if (self.debris2)
+ precache_model(self.debris2);
+ if (self.debris3)
+ precache_model(self.debris3);
+
+ self.use = assault_destructible_use; // shared use function, b/c they woudl do the same thing anyways
+ self.event_damage = func_breakable_damage;
+}
Copied: branches/nexuiz-2.0/data/qcsrc/server/portals.qc (from rev 4363, trunk/data/qcsrc/server/portals.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/portals.qc (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/portals.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -0,0 +1,573 @@
+.vector portal_transform;
+.vector portal_safe_origin;
+.float portal_wants_to_vanish;
+.float portal_activatetime;
+.float portal_id;
+
+.entity portal_in, portal_out;
+
+vector Portal_Transform_Apply(vector transform, vector v)
+{
+ fixedmakevectors(transform);
+ return v_forward * v_x
+ + v_right * (-v_y)
+ + v_up * v_z;
+}
+
+vector Portal_Transform_Multiply(vector t1, vector t2)
+{
+ vector m_forward, m_up;
+ fixedmakevectors(t2); m_forward = v_forward; m_up = v_up;
+ m_forward = Portal_Transform_Apply(t1, m_forward);
+ m_up = Portal_Transform_Apply(t1, m_up);
+ return vectoangles2(m_forward, m_up);
+}
+
+vector Portal_Transform_Invert(vector transform)
+{
+ vector i_forward, i_up;
+ fixedmakevectors(transform);
+ // we want angles that turn v_forward into '1 0 0', v_right into '0 1 0' and v_up into '0 0 1'
+ // but these are orthogonal unit vectors!
+ // so to invert, we can simply vectoangles the TRANSPOSED matrix
+ // TODO is this always -transform?
+ i_forward_x = v_forward_x;
+ i_forward_y = -v_right_x;
+ i_forward_z = v_up_x;
+ i_up_x = v_forward_z;
+ i_up_y = -v_right_z;
+ i_up_z = v_up_z;
+#ifdef DEBUG
+ vector v;
+ v = vectoangles2(i_forward, i_up);
+ print("Transform: ", vtos(transform), "\n");
+ print("Inverted: ", vtos(v), "\n");
+ print("Verify: ", vtos(Portal_Transform_Multiply(v, transform)), "\n");
+ fixedmakevectors(Portal_Transform_Multiply(v, transform));
+ print("Verify: ", vtos(v_forward), "\n");
+ print("Verify: ", vtos(v_right), "\n");
+ print("Verify: ", vtos(v_up), "\n");
+#endif
+ return vectoangles2(i_forward, i_up);
+}
+
+vector Portal_Transform_TurnDirection(vector transform)
+{
+ // turn 180 degrees around v_up
+ // changes in-direction to out-direction
+ fixedmakevectors(transform);
+ return vectoangles2(-1 * v_forward, 1 * v_up);
+}
+
+vector Portal_Transform_Divide(vector to_transform, vector from_transform)
+{
+ return Portal_Transform_Multiply(to_transform, Portal_Transform_Invert(from_transform));
+}
+
+float PlayerEdgeDistance(entity p, vector v)
+{
+ vector vbest;
+
+ if(v_x < 0) vbest_x = p.mins_x; else vbest_x = p.maxs_x;
+ if(v_y < 0) vbest_y = p.mins_y; else vbest_y = p.maxs_y;
+ if(v_z < 0) vbest_z = p.mins_z; else vbest_z = p.maxs_z;
+
+ return vbest * v;
+}
+
+.vector right_vector;
+float Portal_TeleportPlayer(entity teleporter, entity player)
+{
+ vector from, to, safe, step, transform, ang, newvel;
+ float planeshift, s, t;
+ from = teleporter.origin;
+ transform = teleporter.portal_transform;
+
+ to = teleporter.enemy.origin;
+ to = to + Portal_Transform_Apply(teleporter.portal_transform, player.origin - from);
+ newvel = Portal_Transform_Apply(transform, player.velocity);
+ // this now is INSIDE the plane... can't use that
+
+ // shift it out
+ fixedmakevectors(teleporter.enemy.angles);
+
+ // first shift it ON the plane if needed
+ planeshift = ((teleporter.enemy.origin - to) * v_forward) + PlayerEdgeDistance(player, v_forward) + 1;
+ if(planeshift > 0 && (newvel * v_forward) > vlen(newvel) * 0.01)
+ // if we can't, let us not do the planeshift and do somewhat incorrect transformation in the end
+ to += newvel * (planeshift / (newvel * v_forward));
+ else
+ to += trace_plane_normal * planeshift;
+
+ s = (to - teleporter.enemy.origin) * v_right;
+ t = (to - teleporter.enemy.origin) * v_up;
+ s = bound(-48, s, 48);
+ t = bound(-48, t, 48);
+ to = teleporter.enemy.origin
+ + ((to - teleporter.enemy.origin) * v_forward) * v_forward
+ + s * v_right
+ + t * v_up;
+
+ safe = teleporter.enemy.portal_safe_origin; // a valid player origin
+ step = to + ((safe - to) * v_forward) * v_forward;
+ tracebox(safe, PL_MIN, PL_MAX, step, MOVE_NOMONSTERS, player);
+ if(trace_startsolid)
+ {
+ bprint("'safe' teleport location is not safe!\n");
+ // FAIL TODO why does this happen?
+ return 0;
+ }
+ safe = trace_endpos;
+ tracebox(safe, PL_MIN, PL_MAX, to, MOVE_NOMONSTERS, player);
+ if(trace_startsolid)
+ error("trace_endpos in solid!");
+ to = trace_endpos;
+
+ // ang_x stuff works around weird quake angles
+ if(player.classname == "player")
+ {
+ ang = player.v_angle;
+ ang_x = -ang_x;
+ ang = Portal_Transform_Multiply(transform, ang);
+ ang_z = player.angles_z;
+ }
+ else
+ {
+ ang = player.angles;
+ ang_x = -ang_x;
+ ang = Portal_Transform_Multiply(transform, player.angles);
+ }
+ ang_x = -ang_x;
+
+ // factor -1 allows chaining portals, but may be weird
+ player.right_vector = -1 * Portal_Transform_Apply(transform, player.right_vector);
+
+ if(player.flagcarried)
+ DropFlag(player.flagcarried);
+ TeleportPlayer(teleporter, player, to, ang, newvel, teleporter.enemy.absmin, teleporter.enemy.absmax);
+
+ // reset fade counter
+ teleporter.portal_wants_to_vanish = 0;
+ teleporter.fade_time = time + 15;
+ teleporter.enemy.health = 300;
+
+ return 1;
+}
+
+float Portal_FindSafeOrigin(entity portal)
+{
+ vector o;
+ o = portal.origin;
+ portal.mins = PL_MIN - '8 8 8';
+ portal.maxs = PL_MAX + '8 8 8';
+ fixedmakevectors(portal.angles);
+ portal.origin += 16 * v_forward;
+ if(!move_out_of_solid(portal))
+ {
+#ifdef DEBUG
+ print("NO SAFE ORIGIN\n");
+#endif
+ return 0;
+ }
+ portal.portal_safe_origin = portal.origin;
+ setorigin(portal, o);
+ return 1;
+}
+
+void Portal_Touch()
+{
+ if(trace_fraction < 1)
+ return; // only handle TouchAreaGrid ones (only these can teleport)
+ // for some unknown reason, this also gets collisions from SV_Impact sometimes
+ if(!self.enemy)
+ {
+ objerror("Portal_Touch called for [unconnected] portal\n");
+ return;
+ }
+ if(other.classname == "porto")
+ {
+ if(other.portal_id == self.portal_id)
+ return;
+ }
+ if(time < self.portal_activatetime)
+ if(other == self.owner)
+ {
+ self.portal_activatetime = time + 0.1;
+ return;
+ }
+ if(other != self.owner)
+ if(other.classname == "player")
+ if(IS_INDEPENDENT_PLAYER(other) || IS_INDEPENDENT_PLAYER(self.owner))
+ return; // cannot go through someone else's portal
+ if(other.owner != self.owner)
+ if(other.owner.classname == "player")
+ if(IS_INDEPENDENT_PLAYER(other.owner) || IS_INDEPENDENT_PLAYER(self.owner))
+ return; // cannot go through someone else's portal
+ fixedmakevectors(self.angles);
+ if((other.origin - self.origin) * v_forward < 0)
+ return;
+ if(other.mins_x < PL_MIN_x || other.mins_y < PL_MIN_y || other.mins_z < PL_MIN_z
+ || other.maxs_x > PL_MAX_x || other.maxs_y > PL_MAX_y || other.maxs_z > PL_MAX_z)
+ {
+ // can't teleport this
+ return;
+ }
+
+ if(Portal_TeleportPlayer(self, other))
+ if(other.classname == "porto")
+ if(other.effects & EF_RED)
+ other.effects += EF_BLUE - EF_RED;
+}
+
+void Portal_MakeBrokenPortal(entity portal)
+{
+ portal.solid = SOLID_NOT;
+ portal.touch = SUB_Null;
+ portal.effects = 0;
+ //portal.colormod = '1 1 1';
+ portal.nextthink = 0;
+ portal.takedamage = DAMAGE_NO;
+}
+
+void Portal_MakeWaitingPortal(entity portal)
+{
+ portal.solid = SOLID_NOT;
+ portal.touch = SUB_Null;
+ portal.effects = EF_ADDITIVE;
+ portal.colormod = '1 1 1';
+ portal.nextthink = 0;
+ portal.takedamage = DAMAGE_YES;
+}
+
+void Portal_MakeInPortal(entity portal)
+{
+ portal.solid = SOLID_TRIGGER;
+ portal.touch = Portal_Touch;
+ portal.effects = EF_RED;
+ portal.colormod = '1 0 0';
+ portal.nextthink = time;
+ portal.takedamage = DAMAGE_NO;
+}
+
+void Portal_MakeOutPortal(entity portal)
+{
+ portal.solid = SOLID_NOT;
+ portal.touch = SUB_Null;
+ portal.effects = EF_STARDUST | EF_BLUE;
+ portal.colormod = '0 0 1';
+ portal.nextthink = 0;
+ portal.takedamage = DAMAGE_YES;
+}
+
+void Portal_Disconnect(entity teleporter, entity destination)
+{
+ teleporter.enemy = world;
+ destination.enemy = world;
+ Portal_MakeBrokenPortal(teleporter);
+ Portal_MakeBrokenPortal(destination);
+}
+
+void Portal_Connect(entity teleporter, entity destination)
+{
+ teleporter.portal_transform = Portal_Transform_Divide(Portal_Transform_TurnDirection(destination.angles), teleporter.angles);
+
+#ifdef DEBUG
+ {
+ // let's verify the transform
+ vector in_f, in_r, in_u;
+ vector out_f, out_r, out_u;
+ fixedmakevectors(teleporter.angles);
+ in_f = v_forward;
+ in_r = v_right;
+ in_u = v_up;
+ print("teleporter: ", vtos(in_f), " ", vtos(in_r), " ", vtos(in_u), "\n");
+ fixedmakevectors(destination.angles);
+ out_f = v_forward;
+ out_r = v_right;
+ out_u = v_up;
+ print("dest: ", vtos(out_f), " ", vtos(out_r), " ", vtos(out_u), "\n");
+ // INTENDED TRANSFORM:
+ // in_f -> -out_f
+ // in_r -> -out_r
+ // in_u -> +out_u
+ print("FORWARD: ", vtos(in_f), " -> ", vtos(Portal_Transform_Apply(teleporter.portal_transform, in_f)), ", should be", vtos(-1 * out_f), "\n");
+ print("RIGHT: ", vtos(in_r), " -> ", vtos(Portal_Transform_Apply(teleporter.portal_transform, in_r)), ", should be", vtos(-1 * out_r), "\n");
+ print("UP: ", vtos(in_u), " -> ", vtos(Portal_Transform_Apply(teleporter.portal_transform, in_u)), ", should be", vtos(out_u), "\n");
+
+ te_lightning3(world, teleporter.origin, teleporter.origin + in_r * 1000);
+ te_lightning3(world, destination.origin, destination.origin + out_r * 1000);
+ }
+#endif
+
+ teleporter.enemy = destination;
+ destination.enemy = teleporter;
+ Portal_MakeInPortal(teleporter);
+ Portal_MakeOutPortal(destination);
+ teleporter.fade_time = time + 15;
+ destination.fade_time = time + 15;
+ teleporter.portal_wants_to_vanish = 0;
+ destination.portal_wants_to_vanish = 0;
+}
+
+void Portal_Remove(entity portal, float killed)
+{
+ entity e;
+ e = portal.enemy;
+
+ if(e)
+ {
+ Portal_Disconnect(portal, e);
+ Portal_Remove(e, killed);
+ }
+
+ if(portal == portal.owner.portal_in)
+ portal.owner.portal_in = world;
+ if(portal == portal.owner.portal_out)
+ portal.owner.portal_out = world;
+ portal.owner = world;
+
+ // makes the portal vanish
+ if(killed)
+ {
+ fixedmakevectors(portal.angles);
+ pointparticles(particleeffectnum("rocket_explode"), portal.origin + v_forward * 16, v_forward * 1024, 4);
+ remove(portal);
+ }
+ else
+ {
+ Portal_MakeBrokenPortal(portal);
+ SUB_SetFade(portal, time, 0.5);
+ }
+}
+
+void Portal_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if(deathtype == DEATH_TELEFRAG)
+ return;
+ if(attacker != self.owner)
+ if(IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(self.owner))
+ return;
+ self.health -= damage;
+ if(self.health < 0)
+ {
+ Portal_Remove(self, 1);
+ }
+}
+
+void Portal_Think()
+{
+ entity e, o;
+
+ if(self.solid != SOLID_TRIGGER)
+ error("Portal_Think called for a portal that should not be thinking");
+
+ o = self.owner;
+ self.solid = SOLID_BBOX;
+ self.owner = world;
+ FOR_EACH_PLAYER(e)
+ {
+ if(time < self.portal_activatetime)
+ if(e == o)
+ continue;
+ if(e != o)
+ if(IS_INDEPENDENT_PLAYER(e) || IS_INDEPENDENT_PLAYER(o))
+ continue; // cannot go through someone else's portal
+ // if e would hit the portal in a frame...
+ // already teleport him
+ tracebox(e.origin, e.mins, e.maxs, e.origin + e.velocity * 2 * frametime, MOVE_NORMAL, e);
+ if(trace_ent == self)
+ Portal_TeleportPlayer(self, e);
+ }
+ self.solid = SOLID_TRIGGER;
+ self.owner = o;
+
+ self.nextthink = time;
+
+ if(time > self.fade_time)
+ Portal_Remove(self, 0);
+}
+
+float Portal_Customize()
+{
+ if(other.classname == "spectator")
+ other = other.enemy;
+ if(other == self.owner)
+ return TRUE;
+ if(IS_INDEPENDENT_PLAYER(other))
+ return FALSE;
+ if(IS_INDEPENDENT_PLAYER(self.owner))
+ return FALSE;
+ return TRUE;
+}
+
+// cleanup:
+// when creating in-portal:
+// disconnect
+// clear existing in-portal
+// set as in-portal
+// connect
+// when creating out-portal:
+// disconnect
+// clear existing out-portal
+// set as out-portal
+// when player dies:
+// disconnect portals
+// clear both portals
+// after timeout of in-portal:
+// disconnect portals
+// clear both portals
+// TODO: ensure only one portal shot at once
+float Portal_SetInPortal(entity own, entity portal)
+{
+ if(own.portal_in)
+ {
+ if(own.portal_out)
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_Remove(own.portal_in, 0);
+ }
+ own.portal_in = portal;
+ if(own.portal_out)
+ {
+ own.portal_out.portal_id = portal.portal_id;
+ Portal_Connect(own.portal_in, own.portal_out);
+ }
+ return 2;
+}
+float Portal_SetOutPortal(entity own, entity portal)
+{
+ if(own.portal_out)
+ {
+ if(own.portal_in)
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_Remove(own.portal_out, 0);
+ }
+ own.portal_out = portal;
+ if(own.portal_in)
+ {
+ own.portal_in.portal_id = portal.portal_id;
+ Portal_Connect(own.portal_in, own.portal_out);
+ }
+ return 1;
+}
+void Portal_ClearAll(entity own)
+{
+ if(own.portal_in)
+ Portal_Remove(own.portal_in, 0);
+ if(own.portal_out)
+ Portal_Remove(own.portal_out, 0);
+}
+void Portal_ClearWithID(entity own, float id)
+{
+ if(own.portal_in)
+ if(own.portal_in.portal_id == id)
+ {
+ if(own.portal_out)
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_Remove(own.portal_in, 0);
+ }
+ if(own.portal_out)
+ if(own.portal_out.portal_id == id)
+ {
+ if(own.portal_in)
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_Remove(own.portal_out, 0);
+ }
+}
+
+entity Portal_Spawn(entity own, vector org, vector ang)
+{
+ entity portal;
+
+ fixedmakevectors(ang);
+ if(!CheckWireframeBox(own, org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ return world;
+
+ portal = spawn();
+ portal.classname = "portal";
+ portal.owner = own;
+ portal.origin = org;
+ portal.angles = ang;
+ portal.think = Portal_Think;
+ portal.nextthink = 0;
+ portal.fade_time = time + 15;
+ portal.portal_activatetime = time + 0.1;
+ portal.event_damage = Portal_Damage;
+ portal.health = 300;
+ setmodel(portal, "models/portal.md3");
+ portal.customizeentityforclient = Portal_Customize;
+
+ if(!Portal_FindSafeOrigin(portal))
+ {
+ remove(portal);
+ return world;
+ }
+
+ setsize(portal, '-48 -48 -48', '48 48 48');
+ Portal_MakeWaitingPortal(portal);
+
+ return portal;
+}
+
+float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
+{
+ entity portal;
+ vector ang;
+ vector org;
+
+ if(trace_ent.movetype == MOVETYPE_WALK)
+ {
+ trace_endpos = trace_ent.origin + '0 0 1' * PL_MIN_z;
+ trace_plane_normal = '0 0 1';
+ dir = -1 * dir; // create telefrag portals the other way round
+ }
+
+ org = trace_endpos;
+ ang = vectoangles2(trace_plane_normal, dir);
+ fixedmakevectors(ang);
+
+ portal = Portal_Spawn(own, org, ang);
+ if(!portal)
+ {
+ if(!self.portal_out || self.portal_out.portal_id == portal_id_val)
+ Portal_ClearAll(own);
+ return 0;
+ }
+
+ portal.portal_id = portal_id_val;
+ Portal_SetInPortal(own, portal);
+ sound(portal, CHAN_PROJECTILE, "misc/invshot.wav", VOL_BASE, ATTN_NORM);
+
+ return 1;
+}
+
+float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
+{
+ entity portal;
+ vector ang;
+ vector org;
+
+ if(trace_ent.movetype == MOVETYPE_WALK)
+ {
+ trace_endpos = trace_ent.origin + '0 0 1' * PL_MIN_z;
+ trace_plane_normal = '0 0 1';
+ dir = -1 * dir; // create telefrag portals the other way round
+ }
+
+ org = trace_endpos;
+ ang = vectoangles2(trace_plane_normal, dir);
+ fixedmakevectors(ang);
+
+ portal = Portal_Spawn(own, org, ang);
+ if(!portal)
+ {
+ if(!self.portal_in || self.portal_in.portal_id == portal_id_val)
+ Portal_ClearAll(own);
+ return 0;
+ }
+
+ portal.portal_id = portal_id_val;
+ Portal_SetOutPortal(own, portal);
+ sound(portal, CHAN_PROJECTILE, "misc/invshot.wav", VOL_BASE, ATTN_NORM);
+
+ return 1;
+}
Copied: branches/nexuiz-2.0/data/qcsrc/server/portals.qh (from rev 4363, trunk/data/qcsrc/server/portals.qh)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/portals.qh (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/portals.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -0,0 +1,4 @@
+void Portal_ClearAll(entity own);
+float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float id);
+float Portal_SpawnInPortalAtTrace(entity own, vector dir, float id);
+void Portal_ClearWithID(entity own, float id);
Modified: branches/nexuiz-2.0/data/qcsrc/server/progs.src
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/progs.src 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/progs.src 2008-09-05 19:40:34 UTC (rev 4365)
@@ -18,6 +18,8 @@
../common/mapinfo.qh
+portals.qh
+
scores.qh
ipban.qh
@@ -76,8 +78,10 @@
w_electro.qc
w_crylink.qc
w_nex.qc
+w_minstanex.qc
w_hagar.qc
w_rocketlauncher.qc
+w_porto.qc
t_items.qc
cl_weapons.qc
@@ -131,3 +135,5 @@
tturrets/include/turret_tturrets.qh
scores.qc
+
+portals.qc
Modified: branches/nexuiz-2.0/data/qcsrc/server/race.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/race.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/race.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -301,13 +301,61 @@
void checkpoint_touch()
{
+ string oldmsg;
+ entity oldself;
+
+ EXACTTRIGGER_TOUCH;
+
+ if(other.classname == "porto")
+ {
+ // do not allow portalling through checkpoints
+ trace_plane_normal = normalize(-1 * other.velocity);
+ self = other;
+ W_Porto_Fail(0);
+ return;
+ }
+
+ /*
+ * Trigger targets
+ */
+ if not(self.spawnflags & 2)
+ {
+ activator = other;
+ oldmsg = self.message;
+ self.message = "";
+ SUB_UseTargets();
+ self.message = oldmsg;
+ }
+
if(other.classname != "player")
return;
- EXACTTRIGGER_TOUCH;
+ /*
+ * Remove unauthorized equipment
+ */
+ Portal_ClearAll(other);
+ if(other.porto_current)
+ {
+ oldself = self;
+ self = other.porto_current;
+ W_Porto_Fail(1);
+ self = oldself;
+ }
if(other.race_checkpoint == -1 || other.race_checkpoint == self.race_checkpoint)
{
+ /*
+ * Trigger targets
+ */
+ if(self.spawnflags & 2)
+ {
+ activator = other;
+ oldmsg = self.message;
+ self.message = "";
+ SUB_UseTargets();
+ self.message = oldmsg;
+ }
+
other.race_checkpoint = race_NextCheckpoint(self.race_checkpoint);
race_SendTime(other, self.race_checkpoint, time - other.race_laptime, !!other.race_laptime);
Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,6 +1,3 @@
-.float scores[MAX_SCORE];
-.float teamscores[MAX_TEAMSCORE];
-
.entity scorekeeper;
entity teamscorekeepers[16];
string scores_label[MAX_SCORE];
Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qh 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qh 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,4 +1,6 @@
float scores_initialized; // 1 when scores labels/rules have been set
+.float scores[MAX_SCORE];
+.float teamscores[MAX_TEAMSCORE];
/**
* Attaches a PlayerScore entity to a player. Use that in ClientConnect.
Modified: branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -152,6 +152,16 @@
Spawnqueue_Check();
+ // if in warmup stage and limit for warmup is hit start match
+ if (g_tourney
+ && !tourneyInMatchStage
+ && 0 < g_tourney_warmup_limit
+ && (time + RESTART_COUNTDOWN) >= g_tourney_warmup_limit)
+ {
+ ReadyRestart();
+ return;
+ }
+
CreatureFrame ();
CheckRules_World ();
Modified: branches/nexuiz-2.0/data/qcsrc/server/t_items.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_items.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_items.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,4 +1,35 @@
+floatfield Item_CounterField(float it)
+{
+ switch(it)
+ {
+ case IT_SHELLS: return ammo_shells;
+ case IT_NAILS: return ammo_nails;
+ case IT_ROCKETS: return ammo_rockets;
+ case IT_CELLS: return ammo_cells;
+ case IT_5HP: return health;
+ case IT_25HP: return health;
+ case IT_HEALTH: return health;
+ case IT_ARMOR_SHARD: return armorvalue;
+ case IT_ARMOR: return armorvalue;
+ // add more things here (health, armor)
+ default: error("requested item has no counter field");
+ }
+}
+string Item_CounterFieldName(float it)
+{
+ switch(it)
+ {
+ case IT_SHELLS: return "shells";
+ case IT_NAILS: return "nails";
+ case IT_ROCKETS: return "rockets";
+ case IT_CELLS: return "cells";
+
+ // add more things here (health, armor)
+ default: error("requested item has no counter field name");
+ }
+}
+
.float max_armorvalue;
void Item_Respawn (void)
@@ -12,205 +43,247 @@
pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1);
}
-void Item_Touch (void)
+float Item_GiveTo(entity item, entity player)
{
- local entity oldself;
- local float _switchweapon;
- local float pickedup;
- local float it;
+ float _switchweapon;
+ float pickedup;
+ float it;
+ float i;
+ entity e;
- // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
- if (((trace_dpstartcontents | trace_dphitcontents) & DPCONTENTS_NODROP) || (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
- {
- remove(self);
- return;
- }
- if (other.classname != "player")
- return;
- if (other.deadflag)
- return;
- if (self.solid != SOLID_TRIGGER)
- return;
- if (self.owner == other)
- return;
-
- // if nothing happens to other, just return without taking the item
+ // if nothing happens to player, just return without taking the item
pickedup = FALSE;
_switchweapon = FALSE;
if (g_minstagib)
{
_switchweapon = TRUE;
- if (self.ammo_cells)
+ if (item.ammo_cells)
{
pickedup = TRUE;
// play some cool sounds ;)
- centerprint(other, "\n");
- if(other.health <= 5)
- announce(other, "announcer/robotic/lastsecond.ogg");
- else if(other.health < 50)
- announce(other, "announcer/robotic/narrowly.ogg");
+ centerprint(player, "\n");
+ if(player.health <= 5)
+ announce(player, "announcer/robotic/lastsecond.ogg");
+ else if(player.health < 50)
+ announce(player, "announcer/robotic/narrowly.ogg");
// sound not available
- // else if(self.items == IT_CELLS)
- // play2(other, "announce/robotic/ammo.ogg");
+ // else if(item.items == IT_CELLS)
+ // play2(player, "announce/robotic/ammo.ogg");
- if (self.items & IT_NEX)
- W_GiveWeapon (other, IT_NEX, "Nex");
- if (self.ammo_cells)
- other.ammo_cells = min (other.ammo_cells + cvar("g_minstagib_ammo_drop"), 999);
- other.health = 100;
+ if (item.weapons & WEPBIT_MINSTANEX)
+ W_GiveWeapon (player, WEP_MINSTANEX, "Nex");
+ if (item.ammo_cells)
+ player.ammo_cells = min (player.ammo_cells + cvar("g_minstagib_ammo_drop"), 999);
+ player.health = 100;
}
// extralife powerup
- if (self.max_health)
+ if (item.max_health)
{
pickedup = TRUE;
// sound not available
- // play2(other, "announce/robotic/extra.ogg\nplay2 announce/robotic/_lives.ogg");
- other.armorvalue = other.armorvalue + cvar("g_minstagib_extralives");
- sprint(other, "^3You picked up some extra lives\n");
+ // play2(player, "announce/robotic/extra.ogg\nplay2 announce/robotic/_lives.ogg");
+ player.armorvalue = player.armorvalue + cvar("g_minstagib_extralives");
+ sprint(player, "^3You picked up some extra lives\n");
}
// invis powerup
- if (self.strength_finished)
+ if (item.strength_finished)
{
pickedup = TRUE;
// sound not available
- // play2(other, "announce/robotic/invisible.ogg");
- other.strength_finished = max(other.strength_finished, time) + cvar("g_balance_powerup_strength_time");
+ // play2(player, "announce/robotic/invisible.ogg");
+ player.strength_finished = max(player.strength_finished, time) + cvar("g_balance_powerup_strength_time");
}
// speed powerup
- if (self.invincible_finished)
+ if (item.invincible_finished)
{
pickedup = TRUE;
// sound not available
- // play2(other, "announce/robotic/speed.ogg");
- other.invincible_finished = max(other.invincible_finished, time) + cvar("g_balance_powerup_strength_time");
+ // play2(player, "announce/robotic/speed.ogg");
+ player.invincible_finished = max(player.invincible_finished, time) + cvar("g_balance_powerup_strength_time");
}
}
else
{
if (cvar("deathmatch") == 2 || cvar("g_weapon_stay"))
{
- if (self.flags & FL_WEAPON && other.items & self.items && self.classname != "droppedweapon")
- return;
- if (other.items & self.items && self.flags & FL_TOSSED) // don't let players stack ammo by tossing weapons
- return;
+ if (item.flags & FL_WEAPON && player.weapons & item.weapons && item.classname != "droppedweapon")
+ return 0;
+ if (player.weapons & item.weapons && item.flags & FL_TOSSED) // don't let players stack ammo by tossing weapons
+ return 0;
}
// in case the player has autoswitch enabled do the following:
// if the player is using their best weapon before items are given, they
// probably want to switch to an even better weapon after items are given
- if (other.autoswitch)
- if (other.switchweapon == w_getbestweapon(other))
+ if (player.autoswitch)
+ if (player.switchweapon == w_getbestweapon(player))
_switchweapon = TRUE;
- if (self.ammo_shells)
- if (other.ammo_shells < g_pickup_shells_max)
+ if not(player.weapons & W_WeaponBit(player.switchweapon))
+ _switchweapon = TRUE;
+
+ if (item.ammo_shells)
+ if (player.ammo_shells < g_pickup_shells_max)
{
pickedup = TRUE;
- other.ammo_shells = min (other.ammo_shells + self.ammo_shells, g_pickup_shells_max);
+ player.ammo_shells = min (player.ammo_shells + item.ammo_shells, g_pickup_shells_max);
}
- if (self.ammo_nails)
- if (other.ammo_nails < g_pickup_nails_max)
+ if (item.ammo_nails)
+ if (player.ammo_nails < g_pickup_nails_max)
{
pickedup = TRUE;
- other.ammo_nails = min (other.ammo_nails + self.ammo_nails, g_pickup_nails_max);
+ player.ammo_nails = min (player.ammo_nails + item.ammo_nails, g_pickup_nails_max);
}
- if (self.ammo_rockets)
- if (other.ammo_rockets < g_pickup_rockets_max)
+ if (item.ammo_rockets)
+ if (player.ammo_rockets < g_pickup_rockets_max)
{
pickedup = TRUE;
- other.ammo_rockets = min (other.ammo_rockets + self.ammo_rockets, g_pickup_rockets_max);
+ player.ammo_rockets = min (player.ammo_rockets + item.ammo_rockets, g_pickup_rockets_max);
}
- if (self.ammo_cells)
- if (other.ammo_cells < g_pickup_cells_max)
+ if (item.ammo_cells)
+ if (player.ammo_cells < g_pickup_cells_max)
{
pickedup = TRUE;
- other.ammo_cells = min (other.ammo_cells + self.ammo_cells, g_pickup_cells_max);
+ player.ammo_cells = min (player.ammo_cells + item.ammo_cells, g_pickup_cells_max);
}
- if (self.flags & FL_WEAPON)
- if ((it = self.items - (self.items & other.items)))
+ if (item.flags & FL_WEAPON)
+ if ((it = item.weapons - (item.weapons & player.weapons)))
{
pickedup = TRUE;
- if (it & IT_UZI) W_GiveWeapon (other, IT_UZI, self.netname);
- if (it & IT_SHOTGUN) W_GiveWeapon (other, IT_SHOTGUN, self.netname);
- if (it & IT_GRENADE_LAUNCHER) W_GiveWeapon (other, IT_GRENADE_LAUNCHER, self.netname);
- if (it & IT_ELECTRO) W_GiveWeapon (other, IT_ELECTRO, self.netname);
- if (it & IT_NEX) W_GiveWeapon (other, IT_NEX, self.netname);
- if (it & IT_HAGAR) W_GiveWeapon (other, IT_HAGAR, self.netname);
- if (it & IT_ROCKET_LAUNCHER) W_GiveWeapon (other, IT_ROCKET_LAUNCHER, self.netname);
- if (it & IT_CRYLINK) W_GiveWeapon (other, IT_CRYLINK, self.netname);
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ e = get_weaponinfo(i);
+ if(it & e.weapons)
+ W_GiveWeapon (player, e.weapon, item.netname);
+ }
}
- if (self.strength_finished)
+ if (item.strength_finished)
{
pickedup = TRUE;
- other.strength_finished = max(other.strength_finished, time) + cvar("g_balance_powerup_strength_time");
+ player.strength_finished = max(player.strength_finished, time) + cvar("g_balance_powerup_strength_time");
}
- if (self.invincible_finished)
+ if (item.invincible_finished)
{
pickedup = TRUE;
- other.invincible_finished = max(other.invincible_finished, time) + cvar("g_balance_powerup_invincible_time");
+ player.invincible_finished = max(player.invincible_finished, time) + cvar("g_balance_powerup_invincible_time");
}
- //if (self.speed_finished)
+ //if (item.speed_finished)
//{
// pickedup = TRUE;
- // other.speed_finished = max(other.speed_finished, time) + cvar("g_balance_powerup_speed_time");
+ // player.speed_finished = max(player.speed_finished, time) + cvar("g_balance_powerup_speed_time");
//}
- //if (self.slowmo_finished)
+ //if (item.slowmo_finished)
//{
// pickedup = TRUE;
- // other.slowmo_finished = max(other.slowmo_finished, time) + (cvar("g_balance_powerup_slowmo_time") * cvar("g_balance_powerup_slowmo_speed"));
+ // player.slowmo_finished = max(player.slowmo_finished, time) + (cvar("g_balance_powerup_slowmo_time") * cvar("g_balance_powerup_slowmo_speed"));
//}
- if (self.health)
- if (other.health < self.max_health)
+ if (item.health)
+ if (player.health < item.max_health)
{
pickedup = TRUE;
- other.health = min(other.health + self.health, self.max_health);
- other.pauserothealth_finished = max(other.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
+ player.health = min(player.health + item.health, item.max_health);
+ player.pauserothealth_finished = max(player.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
}
- if (self.armorvalue)
- if (other.armorvalue < self.max_armorvalue)
+ if (item.armorvalue)
+ if (player.armorvalue < item.max_armorvalue)
{
pickedup = TRUE;
- other.armorvalue = min(other.armorvalue + self.armorvalue, self.max_armorvalue);
- other.pauserotarmor_finished = max(other.pauserotarmor_finished, time + cvar("g_balance_pause_armor_rot"));
+ player.armorvalue = min(player.armorvalue + item.armorvalue, item.max_armorvalue);
+ player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + cvar("g_balance_pause_armor_rot"));
}
}
+ // always eat teamed entities
+ if(item.team)
+ pickedup = TRUE;
+
if (!pickedup)
- return;
+ return 0;
- sound (other, CHAN_AUTO, self.item_pickupsound, VOL_BASE, ATTN_NORM);
+ sound (player, CHAN_AUTO, item.item_pickupsound, VOL_BASE, ATTN_NORM);
+ if (_switchweapon)
+ W_SwitchWeapon_Force(player, w_getbestweapon(player));
- oldself = self;
- self = other;
+ return 1;
+}
- if (_switchweapon)
- self.switchweapon = w_getbestweapon(self);
- if (self.switchweapon != self.weapon)
- self.cnt = self.weapon;
+void Item_Touch (void)
+{
+ entity e, head;
- self = oldself;
+ // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
+ if (((trace_dpstartcontents | trace_dphitcontents) & DPCONTENTS_NODROP) || (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
+ {
+ remove(self);
+ return;
+ }
+ if (other.classname != "player")
+ return;
+ if (other.deadflag)
+ return;
+ if (self.solid != SOLID_TRIGGER)
+ return;
+ if (self.owner == other)
+ return;
+ if(!Item_GiveTo(self, other))
+ return;
+
if (self.classname == "droppedweapon")
remove (self);
- else if(self.flags & FL_WEAPON && (cvar("deathmatch") == 2 || cvar("g_weapon_stay")))
+ else if((self.flags & FL_WEAPON) && !self.team && (cvar("deathmatch") == 2 || cvar("g_weapon_stay")))
return;
else
{
self.solid = SOLID_NOT;
self.model = string_null;
- self.nextthink = time + self.respawntime;
- self.think = Item_Respawn;
- setorigin (self, self.origin);
+ if(self.team)
+ {
+ RandomSelection_Init();
+ for(head = world; (head = findfloat(head, team, self.team)); ) if(head.flags & FL_ITEM)
+ RandomSelection_Add(head, 0, 1, 0);
+ e = RandomSelection_chosen_ent;
+ }
+ else
+ e = self;
+ e.nextthink = time + self.respawntime;
+ e.think = Item_Respawn;
}
}
+void Item_FindTeam()
+{
+ entity head, e;
+
+ if(self.effects & EF_NODRAW)
+ {
+ // marker for item team search
+ dprint("Initializing item team ", ftos(self.team), "\n");
+ RandomSelection_Init();
+ for(head = world; (head = findfloat(head, team, self.team)); ) if(head.flags & FL_ITEM)
+ RandomSelection_Add(head, 0, 1, 0);
+ e = RandomSelection_chosen_ent;
+
+ for(head = world; (head = findfloat(head, team, self.team)); ) if(head.flags & FL_ITEM)
+ {
+ if(head != e)
+ {
+ // make it a non-spawned item
+ head.solid = SOLID_NOT;
+ head.model = string_null;
+ }
+ head.effects = head.effects - (head.effects & EF_NODRAW);
+ }
+ }
+}
+
// Savage: used for item garbage-collection
// TODO: perhaps nice special effect?
void RemoveItem(void) /*FIXDECL*/
@@ -226,7 +299,7 @@
float weapon_pickupevalfunc(entity player, entity item)
{
// if we already have the weapon, rate it 1/5th normal value
- if ((player.items & item.items) == item.items)
+ if ((player.weapons & item.weapons) == item.weapons)
return item.bot_pickupbasevalue * 0.2;
return item.bot_pickupbasevalue;
};
@@ -257,18 +330,12 @@
if (player.health < item.max_health)
c = c + max(0, 1 - player.health / item.max_health);
- if (cvar("deathmatch") == 2) // weapon stay is on, so weapons the player already has are of no interest
- if (item.flags & FL_WEAPON)
- if (self.items & item.items)
- if (item.classname != "droppedweapon")
- c = 0;
-
return item.bot_pickupbasevalue * c;
};
.float is_item;
-void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, string itemname, float itemid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue)
+void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue)
{
startitem_failed = FALSE;
@@ -374,9 +441,9 @@
self.is_item = TRUE;
}
- itemsInMap |= itemid;
+ weaponsInMap |= weaponid;
- if(g_lms || g_instagib || g_rocketarena)
+ if(g_lms || g_rocketarena)
{
startitem_failed = TRUE;
remove(self);
@@ -403,9 +470,7 @@
precache_sound (pickupsound);
precache_sound ("misc/itemrespawn.wav");
- if(itemid & (IT_STRENGTH | IT_INVINCIBLE | IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2 |
- IT_ROCKET_LAUNCHER | IT_HAGAR | IT_NEX | IT_CRYLINK | IT_ELECTRO |
- IT_GRENADE_LAUNCHER | IT_UZI | IT_SHOTGUN | IT_LASER))
+ if((itemid & (IT_STRENGTH | IT_INVINCIBLE | IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2)) || (weaponid & WEPBIT_ALL))
self.target = "###item###"; // for finding the nearest item using find()
}
@@ -419,6 +484,7 @@
self.respawntime = defaultrespawntime;
self.netname = itemname;
self.items = itemid;
+ self.weapons = weaponid;
self.flags = FL_ITEM | itemflags;
self.touch = Item_Touch;
setmodel (self, self.mdl); // precision set below
@@ -435,6 +501,12 @@
if (cvar("g_fullbrightitems"))
self.effects = self.effects | EF_FULLBRIGHT;
+
+ if(self.team)
+ {
+ self.effects = self.effects | EF_NODRAW; // marker for item team search
+ InitializeEntity(self, Item_FindTeam, INITPRIO_FINDTARGET);
+ }
}
/* replace items in minstagib
@@ -450,7 +522,7 @@
self.ammo_cells = 25;
StartItem ("models/weapons/g_nex.md3",
"weapons/weaponpickup.wav", 15,
- "Nex Gun", IT_NEX, FL_WEAPON, generic_pickupevalfunc, 1000);
+ "MinstaNex", 0, WEPBIT_MINSTANEX, FL_WEAPON, generic_pickupevalfunc, 1000);
return;
}
@@ -463,7 +535,7 @@
self.ammo_cells = 1;
StartItem ("models/items/a_cells.md3",
"misc/itempickup.wav", 45,
- "Nex Ammo", IT_CELLS, 0, generic_pickupevalfunc, 100);
+ "Nex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
return;
}
@@ -482,16 +554,16 @@
self.effects = EF_ADDITIVE;
self.strength_finished = 30;
StartItem ("models/items/g_strength.md3",
- "misc/powerup.wav", 120,
- "Invisibility", IT_STRENGTH, FL_POWERUP, generic_pickupevalfunc, 1000);
+ "misc/powerup.wav", g_pickup_respawntime_powerup,
+ "Invisibility", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
}
// replace with extra lives
if (itemid == IT_NAILS)
{
self.max_health = 1;
StartItem ("models/items/g_h100.md3",
- "misc/megahealth.wav", 120,
- "Extralife", IT_NAILS, FL_POWERUP, generic_pickupevalfunc, 1000);
+ "misc/megahealth.wav", g_pickup_respawntime_powerup,
+ "Extralife", IT_NAILS, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
}
// replace with speed
@@ -500,8 +572,8 @@
self.effects = EF_ADDITIVE;
self.invincible_finished = 30;
StartItem ("models/items/g_invincible.md3",
- "misc/powerup_shield.wav", 120,
- "Speed", IT_INVINCIBLE, FL_POWERUP, generic_pickupevalfunc, 1000);
+ "misc/powerup_shield.wav", g_pickup_respawntime_powerup,
+ "Speed", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, 1000);
}
}
@@ -513,74 +585,81 @@
}
float weaponswapping;
+float internalteam;
+void weapon_defaultspawnfunc(float wpn)
+{
+ entity e;
+ float t;
+ var .float ammofield;
+ string s;
+ entity oldself;
+ float i;
+
+ if(self.classname != "droppedweapon" && self.classname != "replacedweapon")
+ {
+ s = cvar_string(strcat("g_weaponreplace_", ftos(wpn)));
+ t = tokenize(s);
+ if(t >= 2)
+ {
+ self.team = --internalteam;
+ for(i = 1; i < t; ++i)
+ {
+ oldself = self;
+ self = spawn();
+ copyentity(oldself, self);
+ self.classname = "replacedweapon";
+ weapon_defaultspawnfunc(stof(argv(i)));
+ self = oldself;
+ print("replaced by ", argv(i), "\n");
+ }
+ }
+ if(t >= 1)
+ wpn = stof(argv(0));
+ }
+
+ e = get_weaponinfo(wpn);
+
+ t = g_pickup_respawntime_short;
+
+ if(e.items && e.items != IT_SUPERWEAPON)
+ {
+ ammofield = Item_CounterField(e.items);
+ if(!self.ammofield)
+ self.ammofield = cvar(strcat("g_pickup_", Item_CounterFieldName(e.items)));
+ }
+
+ if(e.items == IT_SUPERWEAPON)
+ t = g_pickup_respawntime_powerup;
+
+ StartItem(e.model, "weapons/weaponpickup.wav", t, e.message, 0, e.weapons, FL_WEAPON, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+ if (self.modelindex) // don't precache if self was removed
+ weapon_action(e.weapon, WR_PRECACHE);
+}
+
void spawnfunc_weapon_shotgun (void);
void spawnfunc_weapon_uzi (void) {
- if(!weaponswapping)
if(q3acompat_machineshotgunswap)
if(self.classname != "droppedweapon")
{
- weaponswapping = TRUE;
- spawnfunc_weapon_shotgun();
- weaponswapping = FALSE;
+ weapon_defaultspawnfunc(WEP_SHOTGUN);
return;
}
-
- if(!self.ammo_nails)
- self.ammo_nails = cvar("g_pickup_nails");
- StartItem ("models/weapons/g_uzi.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_UZI), IT_UZI, FL_WEAPON, weapon_pickupevalfunc, 5000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_UZI, WR_PRECACHE);
+ weapon_defaultspawnfunc(WEP_UZI);
}
void spawnfunc_weapon_shotgun (void) {
- if(!weaponswapping)
if(q3acompat_machineshotgunswap)
if(self.classname != "droppedweapon")
{
- weaponswapping = TRUE;
- spawnfunc_weapon_uzi();
- weaponswapping = FALSE;
+ weapon_defaultspawnfunc(WEP_UZI);
return;
}
-
- if(!self.ammo_shells)
- self.ammo_shells = cvar("g_pickup_shells");
- StartItem ("models/weapons/g_shotgun.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_SHOTGUN), IT_SHOTGUN, FL_WEAPON, weapon_pickupevalfunc, 2500);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_SHOTGUN, WR_PRECACHE);
+ weapon_defaultspawnfunc(WEP_SHOTGUN);
}
-void spawnfunc_weapon_grenadelauncher (void)
-{
- if(!self.ammo_rockets)
- self.ammo_rockets = cvar("g_pickup_rockets");
- StartItem ("models/weapons/g_gl.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_GRENADE_LAUNCHER), IT_GRENADE_LAUNCHER, FL_WEAPON, weapon_pickupevalfunc, 5000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_GRENADE_LAUNCHER, WR_PRECACHE);
-}
-
-void spawnfunc_weapon_electro (void)
-{
- if(!self.ammo_cells)
- self.ammo_cells = cvar("g_pickup_cells");
- StartItem ("models/weapons/g_electro.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_ELECTRO), IT_ELECTRO, FL_WEAPON, weapon_pickupevalfunc, 5000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_ELECTRO, WR_PRECACHE);
-}
-
-void spawnfunc_weapon_crylink (void)
-{
- if(!self.ammo_cells)
- self.ammo_cells = cvar("g_pickup_cells");
- StartItem ("models/weapons/g_crylink.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_CRYLINK), IT_CRYLINK, FL_WEAPON, weapon_pickupevalfunc, 2500);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_CRYLINK, WR_PRECACHE);
-}
-
void spawnfunc_weapon_nex (void)
{
- float nextime;
if (g_minstagib)
{
minstagib_items(IT_CELLS);
@@ -588,25 +667,19 @@
self.nextthink = time + cvar("sys_ticrate");
return;
}
- if(!self.ammo_cells)
- self.ammo_cells = cvar("g_pickup_cells");
- nextime = cvar("g_balance_nex_respawntime_modifier");
- if(nextime)
- nextime = 15 * nextime;
- else
- nextime = 15;
- StartItem ("models/weapons/g_nex.md3", "weapons/weaponpickup.wav", nextime, W_Name(WEP_NEX), IT_NEX, FL_WEAPON, weapon_pickupevalfunc, 10000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_NEX, WR_PRECACHE);
+ weapon_defaultspawnfunc(WEP_NEX);
}
-void spawnfunc_weapon_hagar (void)
+void spawnfunc_weapon_minstanex (void)
{
- if(!self.ammo_rockets)
- self.ammo_rockets = cvar("g_pickup_rockets");
- StartItem ("models/weapons/g_hagar.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_HAGAR), IT_HAGAR, FL_WEAPON, weapon_pickupevalfunc, 5000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_HAGAR, WR_PRECACHE);
+ if (g_minstagib)
+ {
+ minstagib_items(IT_CELLS);
+ self.think = minst_remove_item;
+ self.nextthink = time + cvar("sys_ticrate");
+ return;
+ }
+ weapon_defaultspawnfunc(WEP_MINSTANEX);
}
void spawnfunc_weapon_rocketlauncher (void)
@@ -618,17 +691,13 @@
self.nextthink = time + cvar("sys_ticrate");
return;
}
- if(!self.ammo_rockets)
- self.ammo_rockets = g_pickup_rockets;
- StartItem ("models/weapons/g_rl.md3", "weapons/weaponpickup.wav", 15, W_Name(WEP_ROCKET_LAUNCHER), IT_ROCKET_LAUNCHER, FL_WEAPON, weapon_pickupevalfunc, 10000);
- if (self.modelindex) // don't precache if self was removed
- weapon_action(WEP_ROCKET_LAUNCHER, WR_PRECACHE);
+ weapon_defaultspawnfunc(WEP_ROCKET_LAUNCHER);
}
void spawnfunc_item_rockets (void) {
if(!self.ammo_rockets)
self.ammo_rockets = g_pickup_rockets;
- StartItem ("models/items/a_rockets.md3", "misc/itempickup.wav", 15, "rockets", IT_ROCKETS, 0, commodity_pickupevalfunc, 3000);
+ StartItem ("models/items/a_rockets.md3", "misc/itempickup.wav", g_pickup_respawntime_short, "rockets", IT_ROCKETS, 0, 0, commodity_pickupevalfunc, 3000);
}
void spawnfunc_item_shells (void);
@@ -645,13 +714,13 @@
if(!self.ammo_nails)
self.ammo_nails = g_pickup_nails;
- StartItem ("models/items/a_bullets.mdl", "misc/itempickup.wav", 15, "bullets", IT_NAILS, 0, commodity_pickupevalfunc, 2000);
+ StartItem ("models/items/a_bullets.mdl", "misc/itempickup.wav", g_pickup_respawntime_short, "bullets", IT_NAILS, 0, 0, commodity_pickupevalfunc, 2000);
}
void spawnfunc_item_cells (void) {
if(!self.ammo_cells)
self.ammo_cells = g_pickup_cells;
- StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", 15, "cells", IT_CELLS, 0, commodity_pickupevalfunc, 2000);
+ StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_short, "cells", IT_CELLS, 0, 0, commodity_pickupevalfunc, 2000);
}
void spawnfunc_item_shells (void) {
@@ -667,7 +736,7 @@
if(!self.ammo_shells)
self.ammo_shells = g_pickup_shells;
- StartItem ("models/items/a_shells.md3", "misc/itempickup.wav", 15, "shells", IT_SHELLS, 0, commodity_pickupevalfunc, 500);
+ StartItem ("models/items/a_shells.md3", "misc/itempickup.wav", g_pickup_respawntime_short, "shells", IT_SHELLS, 0, 0, commodity_pickupevalfunc, 500);
}
void spawnfunc_item_armor_small (void) {
@@ -675,7 +744,7 @@
self.armorvalue = g_pickup_armorsmall;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armorsmall_max;
- StartItem ("models/items/g_a1.md3", "misc/armor1.wav", 15, "5 Armor", IT_ARMOR_SHARD, 0, commodity_pickupevalfunc, 1000);
+ StartItem ("models/items/g_a1.md3", "misc/armor1.wav", g_pickup_respawntime_short, "5 Armor", IT_ARMOR_SHARD, 0, 0, commodity_pickupevalfunc, 1000);
}
void spawnfunc_item_armor_medium (void) {
@@ -683,7 +752,7 @@
self.armorvalue = g_pickup_armormedium;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armormedium_max;
- StartItem ("models/items/g_armormedium.md3", "misc/armor1.wav", 20, "25 Armor", IT_ARMOR, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_armormedium.md3", "misc/armor1.wav", g_pickup_respawntime_medium, "25 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
}
void spawnfunc_item_armor_large (void) {
@@ -691,7 +760,7 @@
self.armorvalue = g_pickup_armorlarge;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armorlarge_max;
- StartItem ("models/items/g_a25.md3", "misc/armor25.wav", 30, "100 Armor", IT_ARMOR, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_a25.md3", "misc/armor25.wav", g_pickup_respawntime_long, "100 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
}
void spawnfunc_item_health_small (void) {
@@ -699,7 +768,7 @@
self.max_health = g_pickup_healthsmall_max;
if(!self.health)
self.health = g_pickup_healthsmall;
- StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", 15, "5 Health", IT_5HP, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", g_pickup_respawntime_short, "5 Health", IT_5HP, 0, 0, commodity_pickupevalfunc, 20000);
}
void spawnfunc_item_health_medium (void) {
@@ -707,7 +776,7 @@
self.max_health = g_pickup_healthmedium_max;
if(!self.health)
self.health = g_pickup_healthmedium;
- StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", 15, "25 Health", IT_25HP, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", g_pickup_respawntime_short, "25 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, 20000);
}
void spawnfunc_item_health_large (void) {
@@ -715,7 +784,7 @@
self.max_health = g_pickup_healthlarge_max;
if(!self.health)
self.health = g_pickup_healthlarge;
- StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", 20, "50 Health", IT_25HP, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", g_pickup_respawntime_medium, "50 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, 20000);
}
void spawnfunc_item_health_mega (void) {
@@ -732,7 +801,7 @@
self.max_health = g_pickup_healthmega_max;
if(!self.health)
self.health = g_pickup_healthmega;
- StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", 30, "100 Health", IT_HEALTH, 0, commodity_pickupevalfunc, 20000);
+ StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", g_pickup_respawntime_long, "100 Health", IT_HEALTH, 0, 0, commodity_pickupevalfunc, 20000);
}
}
@@ -755,7 +824,8 @@
} else {
precache_sound("weapons/strength_fire.wav");
self.strength_finished = 30;
- self.effects = EF_ADDITIVE;StartItem ("models/items/g_strength.md3", "misc/powerup.wav", 120, "Strength Powerup", IT_STRENGTH, FL_POWERUP, generic_pickupevalfunc, 100000);
+ self.effects = EF_ADDITIVE;
+ StartItem ("models/items/g_strength.md3", "misc/powerup.wav", g_pickup_respawntime_powerup, "Strength Powerup", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
}
}
@@ -771,11 +841,9 @@
} else {
self.invincible_finished = 30;
self.effects = EF_ADDITIVE;
- StartItem ("models/items/g_invincible.md3", "misc/powerup_shield.wav", 120, "Invulnerability", IT_INVINCIBLE, FL_POWERUP, generic_pickupevalfunc, 100000);
+ StartItem ("models/items/g_invincible.md3", "misc/powerup_shield.wav", g_pickup_respawntime_powerup, "Invulnerability", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
}
}
-//void item_speed (void) {self.speed_finished = 30;StartItem ("models/items/g_speed.md3", "misc/powerup.wav", 120, "Speed Powerup", IT_SPEED, FL_POWERUP, generic_pickupevalfunc, 10000);}
-//void item_slowmo (void) {self.slowmo_finished = 30;StartItem ("models/items/g_slowmo.md3", "misc/powerup.wav", 120, "Slow Motion", IT_SLOWMO, FL_POWERUP, generic_pickupevalfunc, 10000);}
void spawnfunc_item_minst_cells (void) {
if (g_minstagib)
@@ -816,55 +884,218 @@
self.use = func_wall_use;
}
-floatfield Item_CounterField(float it)
+float trigger_item_func_set(float a, float b)
{
- switch(it)
+ if(b == 0)
+ return a;
+ else if(b < 0)
+ return 0;
+ else
+ return b;
+}
+
+float trigger_item_func_min(float a, float b)
+{
+ if(b == 0)
+ return a;
+ else if(b < 0)
+ return 0;
+ else
+ return min(a, b);
+}
+
+float trigger_item_func_max(float a, float b)
+{
+ return max(a, b);
+}
+
+float trigger_item_func_bitset(float a, float b)
+{
+ return b;
+}
+
+float trigger_item_func_and(float a, float b)
+{
+ return a & b;
+}
+
+float trigger_item_func_or(float a, float b)
+{
+ return a | b;
+}
+
+float trigger_item_func_andnot(float a, float b)
+{
+ return a - (a & b);
+}
+
+float trigger_item_changed;
+void trigger_item_change(float binary, .float field, float(float a, float b) func, string sound_increase, string sound_decrease)
+{
+ float n, d;
+ n = func(activator.field, self.field);
+
+ if(binary)
{
- case IT_SHELLS: return ammo_shells;
- case IT_NAILS: return ammo_nails;
- case IT_ROCKETS: return ammo_rockets;
- case IT_CELLS: return ammo_cells;
- case IT_5HP: return health;
- case IT_25HP: return health;
- case IT_HEALTH: return health;
- case IT_ARMOR_SHARD: return armorvalue;
- case IT_ARMOR: return armorvalue;
- // add more things here (health, armor)
- default: error("requested item has no counter field");
+ d = n & activator.field;
+ if(d != n) // bits added?
+ d = +1;
+ else if(d != activator.field) // bits removed?
+ d = -1;
+ else
+ d = 0;
}
+ else
+ d = n - activator.field;
+
+ if(d < 0)
+ {
+ if(sound_decrease != "")
+ sound (activator, CHAN_AUTO, sound_decrease, VOL_BASE, ATTN_NORM);
+ trigger_item_changed = 1;
+ }
+ else if(d > 0)
+ {
+ if(sound_increase != "")
+ sound (activator, CHAN_AUTO, sound_increase, VOL_BASE, ATTN_NORM);
+ trigger_item_changed = 1;
+ }
+ activator.field = n;
}
-float Item_WeaponCode(float it)
+void trigger_items_use (void)
{
- switch(it)
+ float h0, a0;
+ if(activator.classname != "player")
+ return;
+ if(activator.deadflag != DEAD_NO)
+ return;
+ EXACTTRIGGER_TOUCH;
+
+ entity e;
+ for(e = world; (e = find(e, classname, "droppedweapon")); )
+ if(e.enemy == activator)
+ remove(e);
+
+ float _switchweapon;
+ _switchweapon = FALSE;
+ if (activator.autoswitch)
+ if (activator.switchweapon == w_getbestweapon(activator))
+ _switchweapon = TRUE;
+
+ a0 = activator.armorvalue;
+ h0 = activator.health;
+ trigger_item_changed = 0;
+
+ if(self.spawnflags == 0) // SET
{
- case IT_LASER: return WEP_LASER;
- case IT_SHOTGUN: return WEP_SHOTGUN;
- case IT_UZI: return WEP_UZI;
- case IT_GRENADE_LAUNCHER: return WEP_GRENADE_LAUNCHER;
- case IT_ELECTRO: return WEP_ELECTRO;
- case IT_CRYLINK: return WEP_CRYLINK;
- case IT_NEX: return WEP_NEX;
- case IT_HAGAR: return WEP_HAGAR;
- case IT_ROCKET_LAUNCHER: return WEP_ROCKET_LAUNCHER;
- default: return 0;
+ trigger_item_change(0, ammo_shells, trigger_item_func_set, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_nails, trigger_item_func_set, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_rockets, trigger_item_func_set, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_cells, trigger_item_func_set, "misc/itempickup.wav", "");
+ trigger_item_change(0, health, trigger_item_func_set, "misc/megahealth.wav", "");
+ trigger_item_change(0, armorvalue, trigger_item_func_set, "misc/armor25.wav", "");
+ trigger_item_change(1, items, trigger_item_func_bitset, "misc/powerup.wav", "");
+ trigger_item_change(1, weapons, trigger_item_func_bitset, "weapons/weaponpickup.wav", "");
+
+ if((self.items & activator.items) & IT_STRENGTH)
+ activator.strength_finished = time + self.strength_finished;
+ if((self.items & activator.items) & IT_INVINCIBLE)
+ activator.invincible_finished = time + self.invincible_finished;
}
+ else if(self.spawnflags == 1) // AND/MIN
+ {
+ trigger_item_change(0, ammo_shells, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_nails, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_rockets, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_cells, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, health, trigger_item_func_min, "misc/megahealth.wav", "");
+ trigger_item_change(0, armorvalue, trigger_item_func_min, "misc/armor25.wav", "");
+ trigger_item_change(1, items, trigger_item_func_and, "misc/powerup.wav", "");
+ trigger_item_change(1, weapons, trigger_item_func_and, "weapons/weaponpickup.wav", "");
+
+ if((self.items & activator.items) & IT_STRENGTH)
+ activator.strength_finished = min(activator.strength_finished, time + self.strength_finished);
+ if((self.items & activator.items) & IT_INVINCIBLE)
+ activator.invincible_finished = min(activator.invincible_finished, time + self.invincible_finished);
+ }
+ else if(self.spawnflags == 2) // OR/MAX
+ {
+ trigger_item_change(0, ammo_shells, trigger_item_func_max, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_nails, trigger_item_func_max, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_rockets, trigger_item_func_max, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_cells, trigger_item_func_max, "misc/itempickup.wav", "");
+ trigger_item_change(0, health, trigger_item_func_max, "misc/megahealth.wav", "");
+ trigger_item_change(0, armorvalue, trigger_item_func_max, "misc/armor25.wav", "");
+ trigger_item_change(1, items, trigger_item_func_or, "misc/powerup.wav", "");
+ trigger_item_change(1, weapons, trigger_item_func_or, "weapons/weaponpickup.wav", "");
+
+ if((self.items & activator.items) & IT_STRENGTH)
+ activator.strength_finished = max(activator.strength_finished, time + self.strength_finished);
+ if((self.items & activator.items) & IT_INVINCIBLE)
+ activator.invincible_finished = max(activator.invincible_finished, time + self.invincible_finished);
+ }
+ else if(self.spawnflags == 4) // ANDNOT/MIN
+ {
+ trigger_item_change(0, ammo_shells, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_nails, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_rockets, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, ammo_cells, trigger_item_func_min, "misc/itempickup.wav", "");
+ trigger_item_change(0, health, trigger_item_func_min, "misc/megahealth.wav", "");
+ trigger_item_change(0, armorvalue, trigger_item_func_min, "misc/armor25.wav", "");
+ trigger_item_change(1, items, trigger_item_func_andnot, "misc/powerup.wav", "");
+ trigger_item_change(1, weapons, trigger_item_func_andnot, "weapons/weaponpickup.wav", "");
+
+ if((self.items & activator.items) & IT_STRENGTH)
+ activator.strength_finished = min(activator.strength_finished, time + self.strength_finished);
+ if((self.items & activator.items) & IT_INVINCIBLE)
+ activator.invincible_finished = min(activator.invincible_finished, time + self.invincible_finished);
+ }
+
+ if not(activator.items & IT_STRENGTH)
+ activator.strength_finished = 0;
+ if not(activator.items & IT_INVINCIBLE)
+ activator.invincible_finished = 0;
+
+ if(activator.health > h0)
+ activator.pauserothealth_finished = max(activator.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
+ else if(activator.health < h0)
+ activator.pauseregen_finished = max(activator.pauseregen_finished, time + cvar("g_balance_pause_health_regen"));
+
+ if(activator.armorvalue > a0)
+ activator.pauserotarmor_finished = max(activator.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
+
+ if not(activator.weapons & W_WeaponBit(activator.switchweapon))
+ _switchweapon = TRUE;
+ if(_switchweapon)
+ W_SwitchWeapon_Force(activator, w_getbestweapon(activator));
+
+ if(trigger_item_changed)
+ centerprint(activator, self.message);
}
-void Item_SpawnByItemCode(float it)
+void spawnfunc_trigger_items (void)
{
- switch(it)
+ float n, i, j;
+ entity e;
+ EXACTTRIGGER_INIT;
+ self.use = trigger_items_use;
+ if(!self.strength_finished)
+ self.strength_finished = cvar("g_balance_powerup_strength_time");
+ if(!self.invincible_finished)
+ self.invincible_finished = cvar("g_balance_powerup_invincible_time");
+
+ n = tokenize(self.netname);
+ for(i = 0; i < n; ++i)
{
- case IT_SHOTGUN: spawnfunc_weapon_shotgun(); break;
- case IT_UZI: spawnfunc_weapon_uzi(); break;
- case IT_GRENADE_LAUNCHER: spawnfunc_weapon_grenadelauncher(); break;
- case IT_ELECTRO: spawnfunc_weapon_electro(); break;
- case IT_CRYLINK: spawnfunc_weapon_crylink(); break;
- case IT_NEX: spawnfunc_weapon_nex(); break;
- case IT_HAGAR: spawnfunc_weapon_hagar(); break;
- case IT_ROCKET_LAUNCHER: spawnfunc_weapon_rocketlauncher(); break;
- // add all other item spawn functions here
- default:
- error("requested item can't be spawned");
+ if(argv(i) == "unlimited_ammo") self.items |= IT_UNLIMITED_AMMO;
+ if(argv(i) == "strength") self.items |= IT_STRENGTH;
+ if(argv(i) == "invincible") self.items |= IT_INVINCIBLE;
+ for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+ {
+ e = get_weaponinfo(j);
+ if(argv(i) == e.netname)
+ self.weapons |= e.weapons;
+ }
}
}
Modified: branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_plats.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1252,6 +1252,9 @@
self.speed = 50;
self.use = fd_secret_use;
IFTARGETED
+ {
+ }
+ else
self.spawnflags |= SECRET_YES_SHOOT;
if(self.spawnflags&SECRET_YES_SHOOT)
Modified: branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_quake.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -53,5 +53,8 @@
require_spawnfunc_prefix = 1;
self.movetypesteplandevent = SUB_Null;
self.viewzoom = 0;
+ self.cvar_cl_weaponpriorities = "";
+ self.scores = 0;
+ self.teamscores = 0;
}
Modified: branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/t_teleporters.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,80 +1,111 @@
-void Teleport_Touch (void)
+.entity pusher;
+void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax)
{
entity head;
entity oldself;
+ entity telefragger;
- if (other.health < 1)
- return;
- if (!other.flags & FL_CLIENT) // FIXME: Make missiles firable through the teleport too
- return;
+ if(teleporter.owner)
+ telefragger = teleporter.owner;
+ else
+ telefragger = player;
- EXACTTRIGGER_TOUCH;
+ sound (player, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
+ pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
- sound (other, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
- pointparticles(particleeffectnum("teleport"), other.origin, '0 0 0', 1);
+ makevectors (to_angles);
+ pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1);
- /*
- // Make teleport effect where the player left
- sound (self, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
- pointparticles(particleeffectnum("teleport"), other.origin, '0 0 0', 1);
+ // Relocate the player
+ // assuming to allows PL_MIN to PL_MAX box and some more
+ setorigin (player, to + '0 0 1' * (1 - player.mins_z - 24));
+ player.angles = to_angles;
+ player.fixangle = TRUE;
+ player.velocity = to_velocity;
- // Make teleport effect where the player arrived
- sound (self.enemy, CHAN_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTN_NORM);
- */
+ if(player.classname == "player")
+ {
+ RemoveGrapplingHook(player);
- makevectors (self.enemy.mangle);
- pointparticles(particleeffectnum("teleport"), self.enemy.origin + v_forward * 32, '0 0 0', 1);
+ // Kill anyone else in the teleporter box (NO MORE TDEATH)
+ if(player.takedamage && player.deadflag == DEAD_NO && !g_race)
+ {
+ vector deathmin;
+ vector deathmax;
+ float deathradius;
+ deathmin = player.absmin;
+ deathmax = player.absmax;
+ if(telefragmin != telefragmax)
+ {
+ if(deathmin_x > telefragmin_x) deathmin_x = telefragmin_x;
+ if(deathmin_y > telefragmin_y) deathmin_y = telefragmin_y;
+ if(deathmin_z > telefragmin_z) deathmin_z = telefragmin_z;
+ if(deathmax_x < telefragmax_x) deathmax_x = telefragmax_x;
+ if(deathmax_y < telefragmax_y) deathmax_y = telefragmax_y;
+ if(deathmax_z < telefragmax_z) deathmax_z = telefragmax_z;
+ }
+ deathradius = max(vlen(deathmin), vlen(deathmax));
+ for(head = findradius(player.origin, deathradius); head; head = head.chain)
+ if(head != player)
+ if(head.takedamage)
+ if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
+ {
+ if ((player.classname == "player") && (player.health >= 1))
+ Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+ else if (telefragger.health < 1) // corpses gib
+ Damage (head, teleporter, telefragger, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+ else // dead bodies and monsters gib themselves instead of telefragging
+ Damage (telefragger, teleporter, telefragger, 10000, DEATH_TELEFRAG, telefragger.origin, '0 0 0');
+ }
+ }
- // Relocate the player
- setorigin (other, self.enemy.origin + '0 0 1' * (1 - other.mins_z - 24));
- other.angles = self.enemy.mangle;
- other.fixangle = TRUE;
- other.velocity = v_forward * vlen(other.velocity);
- RemoveGrapplingHook(other);
+ // hide myself a tic
+ player.effects = player.effects | EF_NODRAW;
+ if (player.weaponentity) // misuse FL_FLY to avoid EF_NODRAW on viewmodel
+ player.weaponentity.flags = player.weaponentity.flags | FL_FLY;
+ player.teleport_time = time + cvar("sys_ticrate");
- // Kill anyone else in the teleporter box (NO MORE TDEATH)
- if(other.takedamage && !g_race)
- {
- vector deathmin;
- vector deathmax;
- float deathradius;
- deathmin = other.absmin;
- deathmax = other.absmax;
- deathradius = max(vlen(deathmin), vlen(deathmax));
- for(head = findradius(other.origin, deathradius); head; head = head.chain)
- if(head != other)
- if(head.takedamage)
- if(boxesoverlap(deathmin, deathmax, head.absmin, head.absmax))
- {
- if ((other.classname == "player") && (other.health >= 1))
- Damage (head, self, other, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
- else if (other.health < 1) // corpses gib
- Damage (head, self, other, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
- else // dead bodies and monsters gib themselves instead of telefragging
- Damage (other, self, other, 10000, DEATH_TELEFRAG, other.origin, '0 0 0');
- }
- }
+ // player no longer is on ground
+ player.flags = player.flags - (player.flags & FL_ONGROUND);
- // hide myself a tic
- other.effects = other.effects | EF_NODRAW;
- if (other.weaponentity) // misuse FL_FLY to avoid EF_NODRAW on viewmodel
- other.weaponentity.flags = other.weaponentity.flags | FL_FLY;
- other.teleport_time = time + cvar("sys_ticrate");
+ // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+ player.oldvelocity = player.velocity;
- other.flags = other.flags - (other.flags & FL_ONGROUND);
- // reset tracking of oldvelocity for impact damage (sudden velocity changes)
- other.oldvelocity = other.velocity;
- // reset tracking of who pushed you into a hazard (for kill credit)
- other.pushltime = 0;
+ // reset tracking of who pushed you into a hazard (for kill credit)
+ if(teleporter.owner)
+ {
+ player.pusher = teleporter.owner;
+ player.pushltime = time + cvar("g_maxpushtime");
+ }
+ else
+ {
+ player.pushltime = 0;
+ }
- // stop player name display
- {
- oldself = self;
- self = other;
- ClearSelectedPlayer();
- self = oldself;
+ // stop player name display
+ {
+ oldself = self;
+ self = player;
+ ClearSelectedPlayer();
+ self = oldself;
+ }
}
+}
+void Teleport_Touch (void)
+{
+ entity oldself;
+
+ if (other.health < 1)
+ return;
+ if (!other.flags & FL_CLIENT) // FIXME: Make missiles firable through the teleport too
+ return;
+
+ EXACTTRIGGER_TOUCH;
+
+ makevectors(self.enemy.mangle);
+ TeleportPlayer(self, other, self.enemy.origin + '0 0 1' * (1 - other.mins_z - 24), self.enemy.mangle, v_forward * vlen(other.velocity), '0 0 0', '0 0 0');
+
if(self.enemy.target)
{
oldself = self;
Modified: branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/teamplay.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -383,8 +383,6 @@
if(g_minstagib)
mutator = "^2Minstagib ^1";
- else if(g_instagib)
- mutator = "^2Instagib ^1";
else if(g_rocketarena)
mutator = "^2Rocketarena ^1";
else if(g_nixnex)
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_common.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_common.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_common.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -6,7 +6,7 @@
if (!wep)
return;
- e.items = e.items | wep;
+ e.weapons = e.weapons | W_WeaponBit(wep);
oldself = self;
self = e;
@@ -141,7 +141,7 @@
{
if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
{
- if (dtype == IT_SHOTGUN)
+ if (dtype == WEP_SHOTGUN)
pointparticles(particleeffectnum("shotgun_impact"), trace_endpos, trace_plane_normal * 1000, 1);
else
pointparticles(particleeffectnum("machinegun_impact"), trace_endpos, trace_plane_normal * 1000, 1);
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_crylink.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -20,7 +20,7 @@
f = cvar("g_balance_crylink_primary_bouncedamagefactor");
if(self.alpha)
f *= self.alpha;
- RadiusDamage (self, self.realowner, cvar("g_balance_crylink_primary_damage") * f, cvar("g_balance_crylink_primary_edgedamage") * f, cvar("g_balance_crylink_primary_radius"), world, cvar("g_balance_crylink_primary_force") * f, IT_CRYLINK);
+ RadiusDamage (self, self.realowner, cvar("g_balance_crylink_primary_damage") * f, cvar("g_balance_crylink_primary_edgedamage") * f, cvar("g_balance_crylink_primary_radius"), world, cvar("g_balance_crylink_primary_force") * f, WEP_CRYLINK);
if (finalhit)
{
remove (self);
@@ -49,7 +49,7 @@
f = cvar("g_balance_crylink_secondary_bouncedamagefactor");
if(self.alpha)
f *= self.alpha;
- RadiusDamage (self, self.realowner, cvar("g_balance_crylink_secondary_damage") * f, cvar("g_balance_crylink_secondary_edgedamage") * f, cvar("g_balance_crylink_secondary_radius"), world, cvar("g_balance_crylink_secondary_force") * f, IT_CRYLINK);
+ RadiusDamage (self, self.realowner, cvar("g_balance_crylink_secondary_damage") * f, cvar("g_balance_crylink_secondary_edgedamage") * f, cvar("g_balance_crylink_secondary_radius"), world, cvar("g_balance_crylink_secondary_force") * f, WEP_CRYLINK);
if (finalhit)
{
remove (self);
@@ -67,7 +67,7 @@
local entity proj;
local vector s;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_cells = self.ammo_cells - cvar("g_balance_crylink_primary_ammo");
W_SetupShot (self, '25 8 -8', FALSE, 2, "weapons/crylink_fire.wav");
@@ -131,7 +131,7 @@
local float counter, shots;
local entity proj;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_cells = self.ammo_cells - cvar("g_balance_crylink_secondary_ammo");
W_SetupShot (self, '25 8 -8', FALSE, 2, "weapons/crylink_fire.wav");
@@ -180,7 +180,7 @@
// experimental lightning gun
void W_Crylink_Attack3 (void)
{
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_cells = self.ammo_cells - cvar("g_balance_crylink_primary_ammo");
W_SetupShot (self, '25 8 -8', TRUE, 0, "weapons/crylink_fire.wav");
@@ -191,10 +191,15 @@
trailparticles(world, particleeffectnum("lightning_beam", w_shotorg, trace_endpos);
if (trace_fraction < 1)
- Damage(trace_ent, self, self, cvar("g_balance_crylink_primary_damage"), IT_CRYLINK, trace_endpos, '0 0 0');
+ Damage(trace_ent, self, self, cvar("g_balance_crylink_primary_damage"), WEP_CRYLINK, trace_endpos, '0 0 0');
}
*/
+void spawnfunc_weapon_crylink (void)
+{
+ weapon_defaultspawnfunc(WEP_CRYLINK);
+}
+
float w_crylink(float req)
{
if (req == WR_AIM)
@@ -229,12 +234,12 @@
precache_sound ("weapons/crylink_fire.wav");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_CRYLINK, "crylink", IT_CELLS);
+ weapon_setup(WEP_CRYLINK);
else if (req == WR_CHECKAMMO1)
return self.ammo_cells >= cvar("g_balance_crylink_primary_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_cells >= cvar("g_balance_crylink_secondary_ammo");
- else if (req == WR_REGISTER)
- weapon_register(WEP_CRYLINK, min(cvar("g_balance_crylink_primary_ammo"), cvar("g_balance_crylink_secondary_ammo")));
+ // else if (req == WR_SUICIDEMESSAGE) // TODO
+ // else if (req == WR_KILLMESSAGE) // TODO
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_electro.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -8,12 +8,12 @@
if (self.movetype == MOVETYPE_BOUNCE)
{
pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1);
- RadiusDamage (self, self.owner, cvar("g_balance_electro_secondary_damage"), cvar("g_balance_electro_secondary_edgedamage"), cvar("g_balance_electro_secondary_radius"), world, cvar("g_balance_electro_secondary_force"), IT_ELECTRO);
+ RadiusDamage (self, self.owner, cvar("g_balance_electro_secondary_damage"), cvar("g_balance_electro_secondary_edgedamage"), cvar("g_balance_electro_secondary_radius"), world, cvar("g_balance_electro_secondary_force"), WEP_ELECTRO);
}
else
{
pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1);
- RadiusDamage (self, self.owner, cvar("g_balance_electro_primary_damage"), cvar("g_balance_electro_primary_edgedamage"), cvar("g_balance_electro_primary_radius"), world, cvar("g_balance_electro_primary_force"), IT_ELECTRO);
+ RadiusDamage (self, self.owner, cvar("g_balance_electro_primary_damage"), cvar("g_balance_electro_primary_edgedamage"), cvar("g_balance_electro_primary_radius"), world, cvar("g_balance_electro_primary_force"), WEP_ELECTRO);
}
sound (self, CHAN_PROJECTILE, "weapons/electro_impact.wav", VOL_BASE, ATTN_NORM);
@@ -29,7 +29,7 @@
sound (self, CHAN_PROJECTILE, "weapons/electro_impact_combo.wav", VOL_BASE, ATTN_NORM);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.owner, cvar("g_balance_electro_combo_damage"), cvar("g_balance_electro_combo_edgedamage"), cvar("g_balance_electro_combo_radius"), world, cvar("g_balance_electro_combo_force"), IT_ELECTRO);
+ RadiusDamage (self, self.owner, cvar("g_balance_electro_combo_damage"), cvar("g_balance_electro_combo_edgedamage"), cvar("g_balance_electro_combo_radius"), world, cvar("g_balance_electro_combo_force"), WEP_ELECTRO);
remove (self);
}
@@ -109,7 +109,7 @@
proj.solid = SOLID_BBOX;
setorigin(proj, w_shotorg);
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_cells = self.ammo_cells - cvar("g_balance_electro_primary_ammo");
proj.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
proj.movetype = MOVETYPE_FLY;
@@ -143,7 +143,7 @@
proj.solid = SOLID_BBOX;
setorigin(proj, w_shotorg);
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_cells = self.ammo_cells - cvar("g_balance_electro_secondary_ammo");
proj.effects = EF_LOWPRECISION;
//proj.glow_size = 50;
@@ -164,6 +164,11 @@
//sound (proj, CHAN_PROJECTILE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM);
}
+void spawnfunc_weapon_electro (void)
+{
+ weapon_defaultspawnfunc(WEP_ELECTRO);
+}
+
.float bot_secondary_electromooth;
float w_electro(float req)
{
@@ -220,12 +225,13 @@
precache_sound ("weapons/electro_impact_combo.wav");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_ELECTRO, "electro", IT_CELLS);
+ weapon_setup(WEP_ELECTRO);
else if (req == WR_CHECKAMMO1)
return self.ammo_cells >= cvar("g_balance_electro_primary_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_cells >= cvar("g_balance_electro_secondary_ammo");
- else if (req == WR_REGISTER)
- weapon_register(WEP_ELECTRO, min(cvar("g_balance_electro_primary_ammo"), cvar("g_balance_electro_secondary_ammo")));
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "played with plasma";
+ // else if (req == WR_KILLMESSAGE) // TODO
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_grenadelauncher.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,4 +1,3 @@
-
void W_Grenade_Explode (void)
{
vector org2;
@@ -7,7 +6,7 @@
sound (self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_primary_damage"), cvar("g_balance_grenadelauncher_primary_edgedamage"), cvar("g_balance_grenadelauncher_primary_radius"), world, cvar("g_balance_grenadelauncher_primary_force"), IT_GRENADE_LAUNCHER);
+ RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_primary_damage"), cvar("g_balance_grenadelauncher_primary_edgedamage"), cvar("g_balance_grenadelauncher_primary_radius"), world, cvar("g_balance_grenadelauncher_primary_force"), WEP_GRENADE_LAUNCHER);
remove (self);
}
@@ -20,7 +19,7 @@
sound (self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_secondary_damage"), cvar("g_balance_grenadelauncher_secondary_edgedamage"), cvar("g_balance_grenadelauncher_secondary_radius"), world, cvar("g_balance_grenadelauncher_secondary_force"), IT_GRENADE_LAUNCHER);
+ RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_secondary_damage"), cvar("g_balance_grenadelauncher_secondary_edgedamage"), cvar("g_balance_grenadelauncher_secondary_radius"), world, cvar("g_balance_grenadelauncher_secondary_force"), WEP_GRENADE_LAUNCHER);
remove (self);
}
@@ -77,7 +76,7 @@
{
local entity gren;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_primary_ammo");
W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
//W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
@@ -112,7 +111,7 @@
{
local entity gren;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_secondary_ammo");
W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
//W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
@@ -147,6 +146,11 @@
gren.flags = FL_PROJECTILE;
}
+void spawnfunc_weapon_grenadelauncher (void)
+{
+ weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER);
+}
+
.float bot_secondary_grenademooth;
float w_glauncher(float req)
{
@@ -202,12 +206,14 @@
precache_sound ("weapons/grenade_impact.wav");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_GRENADE_LAUNCHER, "gl", IT_ROCKETS);
+ weapon_setup(WEP_GRENADE_LAUNCHER);
else if (req == WR_CHECKAMMO1)
return self.ammo_rockets >= cvar("g_balance_grenadelauncher_primary_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_rockets >= cvar("g_balance_grenadelauncher_secondary_ammo");
- else if (req == WR_REGISTER)
- weapon_register(WEP_GRENADE_LAUNCHER, min(cvar("g_balance_grenadelauncher_primary_ammo"), cvar("g_balance_grenadelauncher_secondary_ammo")));
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "detonated";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "was blasted by";
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_hagar.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -13,7 +13,7 @@
sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.realowner, cvar("g_balance_hagar_primary_damage"), cvar("g_balance_hagar_primary_edgedamage"), cvar("g_balance_hagar_primary_radius"), world, cvar("g_balance_hagar_primary_force"), IT_HAGAR);
+ RadiusDamage (self, self.realowner, cvar("g_balance_hagar_primary_damage"), cvar("g_balance_hagar_primary_edgedamage"), cvar("g_balance_hagar_primary_radius"), world, cvar("g_balance_hagar_primary_force"), WEP_HAGAR);
remove (self);
}
@@ -33,7 +33,7 @@
sound (self, CHAN_PROJECTILE, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.realowner, cvar("g_balance_hagar_secondary_damage"), cvar("g_balance_hagar_secondary_edgedamage"), cvar("g_balance_hagar_secondary_radius"), world, cvar("g_balance_hagar_secondary_force"), IT_HAGAR);
+ RadiusDamage (self, self.realowner, cvar("g_balance_hagar_secondary_damage"), cvar("g_balance_hagar_secondary_edgedamage"), cvar("g_balance_hagar_secondary_radius"), world, cvar("g_balance_hagar_secondary_force"), WEP_HAGAR);
remove (self);
}
@@ -80,7 +80,7 @@
{
local entity missile;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_rockets = self.ammo_rockets - cvar("g_balance_hagar_primary_ammo");
W_SetupShot (self, '25 5 -8', FALSE, 2, "weapons/hagar_fire.wav");
//W_SetupShot (self, '25 8 -8', FALSE, 2, "weapons/hagar_fire.wav"); // TODO: move model a little to the right
@@ -119,7 +119,7 @@
{
local entity missile;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_rockets = self.ammo_rockets - cvar("g_balance_hagar_secondary_ammo");
W_SetupShot (self, '25 5 -8', FALSE, 2, "weapons/hagar_fire.wav");
//W_SetupShot (self, '25 8 -8', FALSE, 2, "weapons/hagar_fire.wav"); // TODO: move model a little to the right
@@ -156,6 +156,11 @@
missile.flags = FL_PROJECTILE;
}
+void spawnfunc_weapon_hagar (void)
+{
+ weapon_defaultspawnfunc(WEP_HAGAR);
+}
+
float w_hagar(float req)
{
if (req == WR_AIM)
@@ -193,12 +198,13 @@
precache_sound ("weapons/hagexp3.wav");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_HAGAR, "hagar", IT_ROCKETS);
+ weapon_setup(WEP_HAGAR);
else if (req == WR_CHECKAMMO1)
return self.ammo_rockets >= cvar("g_balance_hagar_primary_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_rockets >= cvar("g_balance_hagar_secondary_ammo");
- else if (req == WR_REGISTER)
- weapon_register(WEP_HAGAR, min(cvar("g_balance_hagar_primary_ammo"), cvar("g_balance_hagar_secondary_ammo")));
+ // else if (req == WR_SUICIDEMESSAGE) // TODO
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "was pummeled by";
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_laser.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -24,9 +24,9 @@
self.event_damage = SUB_Null;
if (self.dmg)
- RadiusDamage (self, self.owner, cvar("g_balance_laser_secondary_damage"), cvar("g_balance_laser_secondary_edgedamage"), cvar("g_balance_laser_secondary_radius"), world, cvar("g_balance_laser_secondary_force"), IT_LASER);
+ RadiusDamage (self, self.owner, cvar("g_balance_laser_secondary_damage"), cvar("g_balance_laser_secondary_edgedamage"), cvar("g_balance_laser_secondary_radius"), world, cvar("g_balance_laser_secondary_force"), WEP_LASER);
else
- RadiusDamage (self, self.owner, cvar("g_balance_laser_primary_damage"), cvar("g_balance_laser_primary_edgedamage"), cvar("g_balance_laser_primary_radius"), world, cvar("g_balance_laser_primary_force"), IT_LASER);
+ RadiusDamage (self, self.owner, cvar("g_balance_laser_primary_damage"), cvar("g_balance_laser_primary_edgedamage"), cvar("g_balance_laser_primary_radius"), world, cvar("g_balance_laser_primary_force"), WEP_LASER);
sound (self, CHAN_PROJECTILE, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
remove (self);
@@ -128,12 +128,12 @@
precache_sound ("weapons/laserimpact.wav");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_LASER, "laser", 0);
+ weapon_setup(WEP_LASER);
else if (req == WR_CHECKAMMO1)
return TRUE;
else if (req == WR_CHECKAMMO2)
return TRUE;
- else if (req == WR_REGISTER)
- weapon_register(WEP_LASER, 0);
+ // else if (req == WR_SUICIDEMESSAGE) // TODO
+ // else if (req == WR_KILLMESSAGE) // TODO
return TRUE;
};
Copied: branches/nexuiz-2.0/data/qcsrc/server/w_minstanex.qc (from rev 4363, trunk/data/qcsrc/server/w_minstanex.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_minstanex.qc (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_minstanex.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -0,0 +1,165 @@
+void W_MinstaNex_Attack (void)
+{
+ float flying;
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+ W_SetupShot (self, '25 8 -4', TRUE, 5, "weapons/nexfire.wav");
+
+ yoda = 0;
+ FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 1000, 800, WEP_MINSTANEX);
+
+ if(!g_minstagib)
+ if(yoda)
+ if(flying)
+ announce(self, "announcer/male/yoda.ogg");
+
+ pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+ // beam effect
+ trailparticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, trace_endpos);
+ // flash and burn the wall
+ if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
+ pointparticles(particleeffectnum("nex_impact"), trace_endpos - w_shotdir * 6, '0 0 0', 1);
+ // play a sound
+ soundat (self, trace_endpos, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
+
+ if not(self.items & IT_UNLIMITED_AMMO)
+ {
+ if (g_minstagib)
+ self.ammo_cells = self.ammo_cells - 1;
+ else
+ self.ammo_cells = self.ammo_cells - cvar("g_balance_minstanex_ammo");
+ }
+}
+
+
+.float minstagib_nextthink;
+void minstagib_ammocheck (void)
+{
+ if (time < self.minstagib_nextthink || self.deadflag || gameover)
+ return;
+
+ if (self.ammo_cells <= 0)
+ {
+ if (self.health == 5)
+ {
+ centerprint(self, "you're dead now...\n");
+ Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/terminated.ogg");
+ }
+ if (self.health == 10)
+ {
+ centerprint(self, "^11^7 second left to find some ammo\n");
+ Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/1.ogg");
+ }
+ if (self.health == 20)
+ {
+ centerprint(self, "^12^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/2.ogg");
+ }
+ if (self.health == 30)
+ {
+ centerprint(self, "^13^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/3.ogg");
+ }
+ if (self.health == 40)
+ {
+ centerprint(self, "^14^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/4.ogg");
+ }
+ if (self.health == 50)
+ {
+ centerprint(self, "^15^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/5.ogg");
+ }
+ if (self.health == 60)
+ {
+ centerprint(self, "^36^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/6.ogg");
+ }
+ if (self.health == 70)
+ {
+ centerprint(self, "^37^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/7.ogg");
+ }
+ if (self.health == 80)
+ {
+ centerprint(self, "^38^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/8.ogg");
+ }
+ if (self.health == 90)
+ {
+ centerprint(self, "^39^7 seconds left to find some ammo\n");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/9.ogg");
+ }
+ if (self.health == 100)
+ {
+ centerprint(self, "get some ammo or\nyou'll be dead in ^310^7 seconds...");
+ Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
+ announce(self, "announcer/robotic/10.ogg");
+ }
+ }
+ self.minstagib_nextthink = time + 1;
+}
+
+void spawnfunc_weapon_minstanex (void); // defined in t_items.qc
+
+float w_minstanex(float req)
+{
+ if (req == WR_AIM)
+ self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
+ else if (req == WR_THINK)
+ {
+ if (self.BUTTON_ATCK)
+ {
+ if (weapon_prepareattack(0, cvar("g_balance_minstanex_refire")))
+ {
+ W_MinstaNex_Attack();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minstanex_animtime"), w_ready);
+ }
+ }
+ else if (self.BUTTON_ATCK2)
+ {
+ if (self.jump_interval <= time)
+ {
+ self.jump_interval = time + 0.9;
+ W_Laser_Attack(FALSE);
+ }
+ }
+ }
+ else if (req == WR_PRECACHE)
+ {
+ precache_model ("models/nexflash.md3");
+ precache_model ("models/weapons/g_minstanex.md3");
+ precache_model ("models/weapons/v_minstanex.md3");
+ precache_model ("models/weapons/w_minstanex.zym");
+ precache_sound ("weapons/nexfire.wav");
+ precache_sound ("weapons/neximpact.wav");
+ w_laser(WR_PRECACHE);
+ }
+ else if (req == WR_SETUP)
+ weapon_setup(WEP_MINSTANEX);
+ else if (req == WR_CHECKAMMO1)
+ {
+ if (g_minstagib)
+ return self.ammo_cells >= 1;
+ else
+ return self.ammo_cells >= cvar("g_balance_minstanex_ammo");
+ }
+ else if (req == WR_CHECKAMMO2)
+ return FALSE;
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "did the impossible";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "has been vaporized by";
+ return TRUE;
+};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_nex.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -1,25 +1,16 @@
-
void W_Nex_Attack (void)
{
float flying;
- if not(g_minstagib || g_instagib)
- flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+ flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
W_SetupShot (self, '25 4 -4', TRUE, 5, "weapons/nexfire.wav");
- //W_SetupShot (self, '25 8 -8', TRUE, 2, "weapons/nexfire.wav"); // TODO: move model down a little
- // assure that nexdamage is high enough in minstagib
- if (g_minstagib || g_instagib)
- FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 1000, 800, IT_NEX);
- else
- {
- yoda = 0;
- FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, cvar("g_balance_nex_damage"), cvar("g_balance_nex_force"), IT_NEX);
+ yoda = 0;
+ FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, cvar("g_balance_nex_damage"), cvar("g_balance_nex_force"), WEP_NEX);
- if(yoda)
- if(flying)
- announce(self, "announcer/male/yoda.ogg");
- }
+ if(yoda)
+ if(flying)
+ announce(self, "announcer/male/yoda.ogg");
pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -31,94 +22,14 @@
// play a sound
soundat (self, trace_endpos, CHAN_PROJECTILE, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
- if (cvar("g_use_ammunition") && !g_instagib)
+ if not(self.items & IT_UNLIMITED_AMMO)
{
- if (g_minstagib)
- self.ammo_cells = self.ammo_cells - 1;
- else
- self.ammo_cells = self.ammo_cells - cvar("g_balance_nex_ammo");
+ self.ammo_cells = self.ammo_cells - cvar("g_balance_nex_ammo");
}
}
+void spawnfunc_weapon_nex (void); // defined in t_items.qc
-.float minstagib_nextthink;
-void minstagib_ammocheck (void)
-{
- if (time < self.minstagib_nextthink || self.deadflag || gameover)
- return;
-
- if (self.ammo_cells <= 0)
- {
- if (self.health == 5)
- {
- centerprint(self, "you're dead now...\n");
- Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/terminated.ogg");
- }
- if (self.health == 10)
- {
- centerprint(self, "^11^7 second left to find some ammo\n");
- Damage(self, self, self, 5, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/1.ogg");
- }
- if (self.health == 20)
- {
- centerprint(self, "^12^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/2.ogg");
- }
- if (self.health == 30)
- {
- centerprint(self, "^13^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/3.ogg");
- }
- if (self.health == 40)
- {
- centerprint(self, "^14^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/4.ogg");
- }
- if (self.health == 50)
- {
- centerprint(self, "^15^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/5.ogg");
- }
- if (self.health == 60)
- {
- centerprint(self, "^36^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/6.ogg");
- }
- if (self.health == 70)
- {
- centerprint(self, "^37^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/7.ogg");
- }
- if (self.health == 80)
- {
- centerprint(self, "^38^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/8.ogg");
- }
- if (self.health == 90)
- {
- centerprint(self, "^39^7 seconds left to find some ammo\n");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/9.ogg");
- }
- if (self.health == 100)
- {
- centerprint(self, "get some ammo or\nyou'll be dead in ^310^7 seconds...");
- Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
- announce(self, "announcer/robotic/10.ogg");
- }
- }
- self.minstagib_nextthink = time + 1;
-}
-
float w_nex(float req)
{
if (req == WR_AIM)
@@ -127,34 +38,12 @@
{
if (self.BUTTON_ATCK)
{
- if(g_minstagib)
+ if (weapon_prepareattack(0, cvar("g_balance_nex_refire")))
{
- if (weapon_prepareattack(0, cvar("g_balance_minstagib_nex_refire")))
- {
- W_Nex_Attack();
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minstagib_nex_animtime"), w_ready);
- }
+ W_Nex_Attack();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_nex_animtime"), w_ready);
}
- else
- {
- if (weapon_prepareattack(0, cvar("g_balance_nex_refire")))
- {
- W_Nex_Attack();
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_nex_animtime"), w_ready);
- }
- }
}
- else if (self.BUTTON_ATCK2)
- {
- if (g_minstagib)
- {
- if (self.jump_interval <= time)
- {
- self.jump_interval = time + 0.9;
- W_Laser_Attack(FALSE);
- }
- }
- }
}
else if (req == WR_PRECACHE)
{
@@ -164,26 +53,16 @@
precache_model ("models/weapons/w_nex.zym");
precache_sound ("weapons/nexfire.wav");
precache_sound ("weapons/neximpact.wav");
- if(g_minstagib)
- w_laser(WR_PRECACHE);
}
else if (req == WR_SETUP)
- weapon_setup(WEP_NEX, "nex", IT_CELLS);
+ weapon_setup(WEP_NEX);
else if (req == WR_CHECKAMMO1)
- {
- if (g_minstagib)
- return self.ammo_cells >= 1;
- else
- return self.ammo_cells >= cvar("g_balance_nex_ammo");
- }
+ return self.ammo_cells >= cvar("g_balance_nex_ammo");
else if (req == WR_CHECKAMMO2)
return FALSE;
- else if (req == WR_REGISTER)
- {
- if(g_minstagib)
- weapon_register(WEP_NEX, 1);
- else
- weapon_register(WEP_NEX, cvar("g_balance_nex_ammo"));
- }
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "did the impossible";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "has been vaporized by";
return TRUE;
};
Copied: branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc (from rev 4363, trunk/data/qcsrc/server/w_porto.qc)
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc (rev 0)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_porto.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -0,0 +1,229 @@
+.float portal_id;
+.entity porto_current;
+.vector porto_v_angle; // holds "held" view angles
+.float porto_v_angle_held;
+.vector right_vector;
+
+void W_Porto_Success (void)
+{
+ self.owner.porto_current = world;
+ remove(self);
+}
+
+float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
+void W_Porto_Fail (float failhard)
+{
+ // no portals here!
+ Portal_ClearWithID(self.owner, self.portal_id);
+ self.owner.porto_current = world;
+
+ if(!failhard && !(self.owner.weapons & WEPBIT_PORTO))
+ {
+ centerprint(self.owner, "^1Portal deployment failed.\n\n^2Catch it to try again!");
+ setsize (self, '-16 -16 0', '16 16 32');
+ setorigin(self, self.origin + trace_plane_normal);
+ if(move_out_of_solid(self))
+ {
+ self.flags = FL_ITEM;
+ self.velocity = trigger_push_calculatevelocity(self.origin, self.owner, 128);
+ tracetoss(self, self);
+ if(vlen(trace_endpos - self.owner.origin) > 128)
+ self.velocity = '0 0 0';
+ W_ThrowNewWeapon(self.owner, WEP_PORTO, 0, self.origin, self.velocity);
+ }
+ else
+ {
+ W_ThrowNewWeapon(self.owner, WEP_PORTO, 0, self.origin, '0 0 0');
+ }
+ }
+ remove(self);
+}
+
+void W_Porto_Think (void)
+{
+ trace_plane_normal = '0 0 0';
+ if(self.owner.playerid != self.playerid)
+ remove(self);
+ else
+ W_Porto_Fail(0);
+}
+
+void W_Porto_Touch (void)
+{
+ vector norm;
+
+ if(other.classname == "portal")
+ return; // handled by the portal
+
+ norm = trace_plane_normal;
+ if(self.owner.playerid != self.playerid)
+ {
+ remove(self);
+ }
+ else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
+ {
+ // just reflect
+ self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
+ self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
+ }
+ else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+ {
+ W_Porto_Fail(0);
+ }
+ else if(self.effects & EF_RED)
+ {
+ self.effects += EF_BLUE - EF_RED;
+ if(Portal_SpawnInPortalAtTrace(self.owner, self.right_vector, self.portal_id))
+ {
+ trace_plane_normal = norm;
+ self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
+ self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
+ }
+ else
+ {
+ trace_plane_normal = norm;
+ W_Porto_Fail(0);
+ }
+ }
+ else
+ {
+ if(Portal_SpawnOutPortalAtTrace(self.owner, self.right_vector, self.portal_id))
+ {
+ W_Porto_Success();
+ }
+ else
+ {
+ trace_plane_normal = norm;
+ W_Porto_Fail(0);
+ }
+ }
+
+}
+
+void W_Porto_Attack (void)
+{
+ local entity gren;
+
+ if not(self.items & IT_UNLIMITED_AMMO)
+ self.weapons = self.weapons - (self.weapons & WEPBIT_PORTO);
+ W_SetupShot (self, '0 0 0', FALSE, 4, "weapons/grenade_fire.wav");
+
+ //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+ gren = spawn ();
+ gren.owner = self;
+ gren.classname = "porto";
+ gren.bot_dodge = TRUE;
+ gren.bot_dodgerating = 200;
+ gren.movetype = MOVETYPE_BOUNCEMISSILE;
+ gren.solid = SOLID_BBOX;
+ gren.effects = EF_LOWPRECISION | EF_RED;
+ gren.scale = 4;
+ gren.modelflags = MF_GRENADE;
+ setmodel(gren, "models/grenademodel.md3"); // precision set above
+ setsize(gren, '0 0 0', '0 0 0');
+ setorigin(gren, w_shotorg);
+
+ gren.nextthink = time + cvar("g_balance_porto_primary_lifetime");
+ gren.think = W_Porto_Think;
+ gren.touch = W_Porto_Touch;
+ gren.velocity = w_shotdir * cvar("g_balance_porto_primary_speed");
+ W_SetupProjectileVelocity(gren);
+
+ gren.angles = vectoangles (gren.velocity);
+ gren.flags = FL_PROJECTILE;
+
+ gren.portal_id = time;
+ self.porto_current = gren;
+ gren.playerid = self.playerid;
+ fixedmakevectors(vectoangles(gren.velocity));
+ gren.right_vector = v_right;
+
+ gren.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+}
+
+void spawnfunc_weapon_porto (void)
+{
+ if(g_race)
+ {
+ startitem_failed = TRUE;
+ remove(self);
+ return;
+ }
+ else
+ weapon_defaultspawnfunc(WEP_PORTO);
+}
+
+float w_porto(float req)
+{
+ vector v_angle_save;
+
+ if (req == WR_AIM)
+ {
+ self.BUTTON_ATCK = FALSE;
+ self.BUTTON_ATCK2 = FALSE;
+ if(bot_aim(cvar("g_balance_porto_primary_speed"), 0, cvar("g_balance_grenadelauncher_primary_lifetime"), FALSE))
+ self.BUTTON_ATCK = TRUE;
+ }
+ else if (req == WR_THINK)
+ {
+ if(self.porto_v_angle_held)
+ {
+ if(!self.BUTTON_ATCK2)
+ {
+ msg_entity = self;
+ WRITESPECTATABLE_MSG_ONE({
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_HOLDANGLES);
+ WriteByte(MSG_ONE, WEP_PORTO);
+ WriteByte(MSG_ONE, 0);
+ });
+ self.porto_v_angle_held = 0;
+ }
+ }
+ else
+ {
+ if(self.BUTTON_ATCK2)
+ {
+ self.porto_v_angle = self.v_angle;
+ msg_entity = self;
+ WRITESPECTATABLE_MSG_ONE({
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_HOLDANGLES);
+ WriteByte(MSG_ONE, WEP_PORTO);
+ WriteByte(MSG_ONE, 1);
+ WriteCoord(MSG_ONE, self.v_angle_x);
+ WriteCoord(MSG_ONE, self.v_angle_y);
+ });
+ self.porto_v_angle_held = 1;
+ }
+ }
+ v_angle_save = self.v_angle;
+ if(self.porto_v_angle_held)
+ makevectors(self.porto_v_angle); // override the previously set angles
+
+ if (self.BUTTON_ATCK)
+ if (!self.porto_current)
+ if (weapon_prepareattack(0, cvar("g_balance_porto_primary_refire")))
+ {
+ W_Porto_Attack();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_porto_primary_animtime"), w_ready);
+ }
+ }
+ else if (req == WR_PRECACHE)
+ {
+ precache_model ("models/grenademodel.md3");
+ precache_model ("models/weapons/g_porto.md3");
+ precache_model ("models/weapons/v_porto.md3");
+ precache_model ("models/weapons/w_porto.zym");
+ precache_sound ("weapons/grenade_fire.wav");
+ precache_model ("models/portal.md3");
+ }
+ else if (req == WR_SETUP)
+ weapon_setup(WEP_PORTO);
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "did the impossible";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "felt # doing the impossible";
+ return TRUE;
+};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_rocketlauncher.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -12,7 +12,7 @@
//effect (org2, "models/sprites/rockexpl.spr", 0, 12, 35);
self.event_damage = SUB_Null;
- RadiusDamage (self, self.owner, cvar("g_balance_rocketlauncher_damage"), cvar("g_balance_rocketlauncher_edgedamage"), cvar("g_balance_rocketlauncher_radius"), world, cvar("g_balance_rocketlauncher_force"), IT_ROCKET_LAUNCHER);
+ RadiusDamage (self, self.owner, cvar("g_balance_rocketlauncher_damage"), cvar("g_balance_rocketlauncher_edgedamage"), cvar("g_balance_rocketlauncher_radius"), world, cvar("g_balance_rocketlauncher_force"), WEP_ROCKET_LAUNCHER);
if (self.owner.weapon == WEP_ROCKET_LAUNCHER)
{
@@ -213,7 +213,7 @@
local entity missile;
local entity flash, flash2;
- if (cvar("g_use_ammunition") && !g_rocketarena)
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_rockets = self.ammo_rockets - cvar("g_balance_rocketlauncher_ammo");
W_SetupShot (self, '25 3 -4', FALSE, 5, "weapons/rocket_fire.wav");
@@ -283,6 +283,8 @@
flash.effects = flash2.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
}
+void spawnfunc_weapon_rocketlauncher (void); // defined in t_items.qc
+
float w_rlauncher(float req)
{
if (req == WR_AIM)
@@ -418,7 +420,7 @@
precache_model ("models/laser_dot.mdl"); // rocket launcher
}
else if (req == WR_SETUP)
- weapon_setup(WEP_ROCKET_LAUNCHER, "rl", IT_ROCKETS);
+ weapon_setup(WEP_ROCKET_LAUNCHER);
else if (req == WR_CHECKAMMO1)
{
// don't switch while guiding a missile
@@ -428,7 +430,9 @@
}
else if (req == WR_CHECKAMMO2)
return FALSE;
- else if (req == WR_REGISTER)
- weapon_register(WEP_ROCKET_LAUNCHER, cvar("g_balance_rocketlauncher_ammo"));
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "exploded";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "almost dodged #'s rocket";
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_shotgun.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_shotgun.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_shotgun.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -15,8 +15,8 @@
W_SetupShot (self, '25 8 -8', TRUE, 5, "weapons/shotgun_fire.wav");
for (sc = 0;sc < bullets;sc = sc + 1)
- fireBullet (w_shotorg, w_shotdir, spread, d, f, IT_SHOTGUN, sc < 3);
- if (cvar("g_use_ammunition"))
+ fireBullet (w_shotorg, w_shotdir, spread, d, f, WEP_SHOTGUN, sc < 3);
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_shells = self.ammo_shells - cvar("g_balance_shotgun_primary_ammo");
pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_primary_ammo"));
@@ -58,8 +58,8 @@
W_SetupShot (self, '25 8 -8', TRUE, 5, "weapons/shotgun_fire.wav");
for (sc = 0;sc < bullets;sc = sc + 1)
- fireBullet (w_shotorg, w_shotdir, spread, d, f, IT_SHOTGUN, sc < 3);
- if (cvar("g_use_ammunition"))
+ fireBullet (w_shotorg, w_shotdir, spread, d, f, WEP_SHOTGUN, sc < 3);
+ if not(self.items & IT_UNLIMITED_AMMO)
self.ammo_shells = self.ammo_shells - cvar("g_balance_shotgun_secondary_ammo");
pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_secondary_ammo"));
@@ -95,6 +95,8 @@
weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_shotgun_secondary_animtime"), shotgun_fire2_03);
}
+void spawnfunc_weapon_shotgun(); // defined in t_items.qc
+
float w_shotgun(float req)
{
if (req == WR_AIM)
@@ -134,12 +136,14 @@
precache_model ("models/casing_shell.mdl");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_SHOTGUN, "shotgun", IT_SHELLS);
+ weapon_setup(WEP_SHOTGUN);
else if (req == WR_CHECKAMMO1)
return self.ammo_shells >= cvar("g_balance_shotgun_primary_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_shells >= cvar("g_balance_shotgun_secondary_ammo") * 3;
- else if (req == WR_REGISTER)
- weapon_register(WEP_SHOTGUN, min(cvar("g_balance_shotgun_primary_ammo"), cvar("g_balance_shotgun_secondary_ammo")));
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "did the impossible";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "was gunned by";
return TRUE;
};
Modified: branches/nexuiz-2.0/data/qcsrc/server/w_uzi.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/w_uzi.qc 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/qcsrc/server/w_uzi.qc 2008-09-05 19:40:34 UTC (rev 4365)
@@ -15,7 +15,7 @@
{
local entity flash, flash2;
- if (cvar("g_use_ammunition"))
+ if not(self.items & IT_UNLIMITED_AMMO)
{
if (self.uzi_bulletcounter == 1)
self.ammo_nails = self.ammo_nails - cvar("g_balance_uzi_first_ammo");
@@ -34,9 +34,9 @@
ATTACK_FINISHED(self) = time + cvar("g_balance_uzi_first_refire");
if (self.uzi_bulletcounter == 1)
- fireBullet (w_shotorg, w_shotdir, cvar("g_balance_uzi_first_spread"), cvar("g_balance_uzi_first_damage"), cvar("g_balance_uzi_first_force"), IT_UZI, TRUE);
+ fireBullet (w_shotorg, w_shotdir, cvar("g_balance_uzi_first_spread"), cvar("g_balance_uzi_first_damage"), cvar("g_balance_uzi_first_force"), WEP_UZI, TRUE);
else
- fireBullet (w_shotorg, w_shotdir, cvar("g_balance_uzi_sustained_spread"), cvar("g_balance_uzi_sustained_damage"), cvar("g_balance_uzi_sustained_force"), IT_UZI, (self.uzi_bulletcounter & 3) == 0);
+ fireBullet (w_shotorg, w_shotdir, cvar("g_balance_uzi_sustained_spread"), cvar("g_balance_uzi_sustained_damage"), cvar("g_balance_uzi_sustained_force"), WEP_UZI, (self.uzi_bulletcounter & 3) == 0);
pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -85,9 +85,7 @@
{
if (!weapon_action(self.weapon, WR_CHECKAMMO2))
{
- self.switchweapon = w_getbestweapon(self);
- if (self.switchweapon != self.weapon)
- self.cnt = self.weapon;
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
w_ready();
return;
}
@@ -100,6 +98,8 @@
weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_uzi_sustained_refire"), w_ready);
};
+void spawnfunc_weapon_machinegun(); // defined in t_items.qc
+
float w_uzi(float req)
{
if (req == WR_AIM)
@@ -142,12 +142,14 @@
precache_model ("models/casing_bronze.mdl");
}
else if (req == WR_SETUP)
- weapon_setup(WEP_UZI, "uzi", IT_NAILS);
+ weapon_setup(WEP_UZI);
else if (req == WR_CHECKAMMO1)
return self.ammo_nails >= cvar("g_balance_uzi_first_ammo");
else if (req == WR_CHECKAMMO2)
return self.ammo_nails >= cvar("g_balance_uzi_first_ammo");
- else if (req == WR_REGISTER)
- weapon_register(WEP_UZI, cvar("g_balance_uzi_first_ammo"));
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "did the impossible";
+ else if (req == WR_KILLMESSAGE)
+ w_deathtypestring = "was riddled full of holes by";
return TRUE;
};
Modified: branches/nexuiz-2.0/data/scripts/entities.def
===================================================================
--- branches/nexuiz-2.0/data/scripts/entities.def 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/scripts/entities.def 2008-09-05 19:40:34 UTC (rev 4365)
@@ -274,6 +274,7 @@
respawntime: time till it respawns (default: 30)
armorvalue: amount of armor it gives (default: 100 (g_pickup_armorlarge))
max_armorvalue: max of armor it increases to (default: 999 (g_pickup_armorlarge_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -286,6 +287,7 @@
respawntime: time till it respawns (default: 20)
armorvalue: amount of armor it gives (default: 25 (g_pickup_armormedium))
max_armorvalue: max of armor it increases to (default: 999 (g_pickup_armormedium_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -298,6 +300,7 @@
respawntime: time till it respawns (default: 15)
armorvalue: amount of armor it gives (default: 5 (g_pickup_armorsmall))
max_armorvalue: max of armor it increases to (default: 999 (g_pickup_armorsmall_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -309,6 +312,7 @@
-------- KEYS --------
ammo_nails: bullets gained by this item (if unset, g_pickup_nails is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -320,6 +324,7 @@
-------- KEYS --------
ammo_cells: cells gained by this item (if unset, g_pickup_cells is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -354,6 +359,7 @@
respawntime: time till it respawns (default: 20)
health: amount of health it gives (default: 50 (g_pickup_healthlarge))
max_health: max of health it increases to (default: 999 (g_pickup_healthlarge_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -366,6 +372,7 @@
respawntime: time till it respawns (default: 15)
health: amount of health it gives (default: 25 (g_pickup_healthmedium))
max_health: max of health it increases to (default: 999 (g_pickup_healthmedium_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -379,6 +386,7 @@
respawntime: time till it respawns (default: 30)
health: amount of health it gives (default: 100 (g_pickup_healthmega))
max_health: max of health it increases to (default: 999 (g_pickup_healthmega_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -391,6 +399,7 @@
respawntime: time till it respawns (default: 15)
health: amount of health it gives (default: 5 (g_pickup_healthsmall))
max_health: max of health it increases to (default: 5 (g_pickup_healthsmall_max))
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -402,6 +411,7 @@
In Minstagib, this randomly turns into either an invisibility, an extra lives or a speed power-up with a default respawn time of 120.
-------- KEYS --------
respawntime: time till it respawns (default: 120)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -414,6 +424,7 @@
It only appears when playing Minstagib and prevents auto-replacement of weapon_nex & weapon_rocketlauncher when used.
-------- KEYS --------
respawntime: time till it respawns (default: 45)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -425,6 +436,7 @@
-------- KEYS --------
ammo_rockets: rockets gained by this item (if unset, g_pickup_rockets is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -436,6 +448,7 @@
-------- KEYS --------
ammo_shells: shells gained by this item (if unset, g_pickup_shells is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -447,6 +460,7 @@
In Minstagib, this randomly turns into either an invisibility, an extra lives or a speed power-up with a default respawn time of 120.
-------- KEYS --------
respawntime: time till it respawns (default: 120)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -500,7 +514,7 @@
Laser beam emitter
-------- KEYS --------
target: target_position the laser targets (may be another entity, preferably target_position, possibly controlled by misc_follow)
-mdl: name of particle effect for the beam end point (see effectinfo.txt; default is misc_laser_beam_end)
+mdl: name of particle effect for the beam end point (see effectinfo.txt; default is laser_deadly if dmg is set, and none if not)
colormod: color of the laser beam (default: red, that is, 1 0 0)
dmg: damage inflicted by the beam per second, or -1 for an instant-death ray
targetname: name to target this (then its state is toggled)
@@ -658,6 +672,8 @@
-------- KEYS --------
noise: path/name of .wav/.ogg file to play
targetname: the activating button or trigger points to this.
+atten: distance attenuation of the sound (a value from 0.1 to 3.9), default is 0.5 if targeted, 3 otherwise; set to -1 for no attenuation (global sound)
+volume: volume of the sound
*/
/*QUAKED trigger_counter (.5 .5 .5) ? NOMESSAGE
@@ -783,6 +799,7 @@
-------- KEYS --------
ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -794,6 +811,7 @@
-------- KEYS --------
ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -805,6 +823,7 @@
-------- KEYS --------
ammo_rockets: initial rockets of the weapon (if unset, g_pickup_rockets is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -816,6 +835,7 @@
-------- KEYS --------
ammo_rockets: initial rockets of the weapon (if unset, g_pickup_rockets is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -828,6 +848,7 @@
-------- KEYS --------
ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
respawntime: time till it respawns (default: 15 * g_balance_nex_respawntime_modifier)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -840,6 +861,7 @@
-------- KEYS --------
ammo_rockets: initial rockets of the weapon (if unset, g_pickup_rockets is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -851,6 +873,7 @@
-------- KEYS --------
ammo_shells: initial shells of the weapon (if unset, g_pickup_shells is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -862,6 +885,7 @@
-------- KEYS --------
ammo_nails: initial bullets of the weapon (if unset, g_pickup_nails is used)
respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
-------- SPAWNFLAGS --------
FLOATING: the item will float in air, instead of aligning to the floor by falling
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
@@ -894,14 +918,16 @@
_celshader: Sets the cel shader used for this geometry. Note: omit the "textures/" prefix.
*/
-/*QUAKED trigger_race_checkpoint (0 1 0) ? NOTOUCH - CRUSH
+/*QUAKED trigger_race_checkpoint (0 1 0) ? NOTOUCH STRICTTRIGGER CRUSH
A checkpoint, for the race game mode. Be sure to make them quite long, so they actually catch a player reliably!
-------- KEYS --------
cnt: Number of the checkpoint. 0 for finish line, and at least two other checkpoints have to exist. They MUST be touched in sequential order!
message: Death message, when touching checkpoints in the wrong order.
targetname: Name of the checkpoint. info_player_race can target this to assign a spawn to a checkpoint. Also used for triggering a checkpoint by an event.
+target: when the checkpoint is passed, these entities are triggered. Useful for forcing items in certain areas using trigger_items
-------- SPAWNFLAGS --------
NOTOUCH: the checkpoint will not become active when touched, it HAS to be targeted
+STRICTTRIGGER: only trigger the targets when the checkpoint actually was reached in a valid way (that is, not when going back)
CRUSH: the checkpoint kills when used at the wrong time
*/
@@ -969,3 +995,47 @@
target: points to the entity to move (e.g. something that won't move by itself)
killtarget: points to the entity that is to be used as the source (e.g. a func_plat)
*/
+
+/*QUAKED weapon_minstanex (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
+the MinstaGib Nex. Always kills with one shot.
+-------- KEYS --------
+ammo_cells: initial cells of the weapon (if unset, g_pickup_cells is used)
+respawntime: time till it respawns (default: 15)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/weapons/g_minstanex.md3"
+*/
+
+/*QUAKED weapon_porto (1 0 .5) (-30 -30 0) (30 30 32) FLOATING
+the Port-O-Launch. Only can be shot once.
+Portals cannot be made on noimpact surfaces, and the portal missile will bounce on slick surfaces.
+-------- KEYS --------
+respawntime: time till it respawns (default: 120)
+team: out of items with the same value here, only one (random one) will spawn. Useful to put multiple items on one spot.
+-------- SPAWNFLAGS --------
+FLOATING: the item will float in air, instead of aligning to the floor by falling
+-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
+model="models/weapons/g_porto.md3"
+*/
+
+/*QUAKED trigger_items (0 0 1) (-8 -8 -8) (8 8 8) AND OR ANDNOT
+Sets the items of any player who triggers this.
+For the number fields, not specifying a value means not changing it. To clear armor, you need to explicitly set "armor" to "-1".
+-------- KEYS --------
+netname: space separated list of items (either weapon short names (like in g_start_weapon_* cvars), or item short names "unlimited_ammo", "invincible" and "strength"
+message: message to print
+ammo_shells: amount of shells
+ammo_nails: amount of bullets
+ammo_rockets: amount of rockets
+ammo_cells: amount of cells
+health: amount of health
+armorvalue: amount of armor
+strength_finished: if "strength" is specified, the time in seconds for which the strength will hold
+invincible_finished: if "invincible" is specified, the time in seconds for which the invincibility will hold
+-------- SPAWNFLAGS --------
+AND: any items not listed will get removed, and none will get added
+OR: the player may keep items not listed
+ANDNOT: the items listed will get removed from the player
+*/
Copied: branches/nexuiz-2.0/data/textures/nex.tga (from rev 4363, trunk/data/textures/nex.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/nex_bump.tga (from rev 4363, trunk/data/textures/nex_bump.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/nex_gloss.tga (from rev 4363, trunk/data/textures/nex_gloss.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/nex_glow.tga (from rev 4363, trunk/data/textures/nex_glow.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/nex_pants.tga (from rev 4363, trunk/data/textures/nex_pants.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/nex_shirt.tga (from rev 4363, trunk/data/textures/nex_shirt.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/portalgun.tga (from rev 4363, trunk/data/textures/portalgun.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/portalgun_gloss.tga (from rev 4363, trunk/data/textures/portalgun_gloss.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/portalgun_glow.tga (from rev 4363, trunk/data/textures/portalgun_glow.tga)
===================================================================
(Binary files differ)
Copied: branches/nexuiz-2.0/data/textures/portalgun_norm.tga (from rev 4363, trunk/data/textures/portalgun_norm.tga)
===================================================================
(Binary files differ)
Modified: branches/nexuiz-2.0/data/weapons.cfg
===================================================================
--- branches/nexuiz-2.0/data/weapons.cfg 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/weapons.cfg 2008-09-05 19:40:34 UTC (rev 4365)
@@ -7,6 +7,8 @@
set g_start_weapon_nex 0
set g_start_weapon_hagar 0
set g_start_weapon_rocketlauncher 0
+set g_start_weapon_minstanex 0
+set g_start_weapon_porto 0
set g_start_ammo_shells 50
set g_start_ammo_nails 0
set g_start_ammo_rockets 0
@@ -33,6 +35,10 @@
set g_pickup_healthlarge_max 999
set g_pickup_healthmega 100
set g_pickup_healthmega_max 999
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
set g_balance_laser_primary_damage 35
set g_balance_laser_primary_edgedamage 10
@@ -166,11 +172,12 @@
set g_balance_nex_force 600
set g_balance_nex_refire 1.5
set g_balance_nex_animtime 0.3
-set g_balance_minstagib_nex_refire 1.5
-set g_balance_minstagib_nex_animtime 0.3
set g_balance_nex_ammo 5
-set g_balance_nex_respawntime_modifier 1
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+
set g_balance_hagar_primary_damage 40
set g_balance_hagar_primary_edgedamage 15
set g_balance_hagar_primary_force 100
@@ -191,10 +198,10 @@
set g_balance_hagar_secondary_ammo 1
set g_balance_rocketlauncher_damage 130
-set g_balance_rocketlauncher_edgedamage 50
+set g_balance_rocketlauncher_edgedamage 20
set g_balance_rocketlauncher_force 600
-set g_balance_rocketlauncher_radius 170
-set g_balance_rocketlauncher_speed 850
+set g_balance_rocketlauncher_radius 150
+set g_balance_rocketlauncher_speed 880
set g_balance_rocketlauncher_speedaccel 0
set g_balance_rocketlauncher_speedstart 850
set g_balance_rocketlauncher_lifetime 30
@@ -207,3 +214,9 @@
set g_balance_rocketlauncher_laserguided_speedstart 1000
set g_balance_rocketlauncher_laserguided_turnrate 0.75 //0.5
set g_balance_rocketlauncher_laserguided_allow_steal 1
+
+// TESTING: port-o-launch
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_speed 2000
+set g_balance_porto_primary_lifetime 30
+set g_balance_porto_primary_ammo 25
Modified: branches/nexuiz-2.0/data/weaponsPro.cfg
===================================================================
--- branches/nexuiz-2.0/data/weaponsPro.cfg 2008-09-05 19:39:18 UTC (rev 4364)
+++ branches/nexuiz-2.0/data/weaponsPro.cfg 2008-09-05 19:40:34 UTC (rev 4365)
@@ -7,6 +7,8 @@
set g_start_weapon_nex 0
set g_start_weapon_hagar 0
set g_start_weapon_rocketlauncher 0
+set g_start_weapon_minstanex 0
+set g_start_weapon_porto 0
set g_start_ammo_shells 40
set g_start_ammo_nails 0
set g_start_ammo_rockets 0
@@ -33,6 +35,10 @@
set g_pickup_healthlarge_max 100
set g_pickup_healthmega 100
set g_pickup_healthmega_max 200
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
set g_balance_laser_primary_damage 20
set g_balance_laser_primary_edgedamage 10
@@ -131,12 +137,19 @@
set g_balance_crylink_primary_speed 7000
set g_balance_crylink_primary_spread 0
set g_balance_crylink_primary_shots 1
-set g_balance_crylink_primary_lifetime 30
set g_balance_crylink_primary_bounces 0
set g_balance_crylink_primary_refire 0.1
set g_balance_crylink_primary_animtime 0.1
set g_balance_crylink_primary_ammo 1
set g_balance_crylink_primary_bouncedamagefactor 0.5
+
+set g_balance_crylink_primary_middle_lifetime 30 // range: virtually infinite
+set g_balance_crylink_primary_middle_fadetime 0
+set g_balance_crylink_primary_star_lifetime 0.1 // range: 700 full, fades to 2100
+set g_balance_crylink_primary_star_fadetime 0.2
+set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2100
+set g_balance_crylink_primary_other_fadetime 0.2
+
set g_balance_crylink_secondary_damage 15
set g_balance_crylink_secondary_edgedamage 0
set g_balance_crylink_secondary_force 100
@@ -144,22 +157,27 @@
set g_balance_crylink_secondary_speed 7000
set g_balance_crylink_secondary_spread 0.08
set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_lifetime 30
set g_balance_crylink_secondary_bounces 0
set g_balance_crylink_secondary_refire 0.6
set g_balance_crylink_secondary_animtime 0.3
set g_balance_crylink_secondary_ammo 5
set g_balance_crylink_secondary_bouncedamagefactor 0.5
+set g_balance_crylink_secondary_middle_lifetime 30 // range: virtually infinite
+set g_balance_crylink_secondary_middle_fadetime 0
+set g_balance_crylink_secondary_line_lifetime 30 // range: virtually infinite
+set g_balance_crylink_secondary_line_fadetime 0
+
set g_balance_nex_damage 70
set g_balance_nex_force 0
set g_balance_nex_refire 0.7
set g_balance_nex_animtime 0.3
-set g_balance_minstagib_nex_refire 1.5
-set g_balance_minstagib_nex_animtime 0.3
set g_balance_nex_ammo 5
-set g_balance_nex_respawntime_modifier 1
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+
set g_balance_hagar_primary_damage 40
set g_balance_hagar_primary_edgedamage 20
set g_balance_hagar_primary_force 0
@@ -196,3 +214,9 @@
set g_balance_rocketlauncher_laserguided_speedstart 1000
set g_balance_rocketlauncher_laserguided_turnrate 0.75 //0.5
set g_balance_rocketlauncher_laserguided_allow_steal 1
+
+// TESTING: port-o-launch
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_speed 2000
+set g_balance_porto_primary_lifetime 30
+set g_balance_porto_primary_ammo 25
More information about the nexuiz-commits
mailing list