[nexuiz-commits] r6568 - in trunk: Docs data data/gfx data/models data/models/nexball data/qcsrc/client data/qcsrc/common data/qcsrc/server data/scripts data/sound data/sound/nexball data/textures data/textures/nexball misc/mediasource/graphics
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Wed Apr 22 13:52:54 EDT 2009
Author: mrbougo
Date: 2009-04-22 13:52:53 -0400 (Wed, 22 Apr 2009)
New Revision: 6568
Added:
trunk/data/gfx/sb_nexball_carrying.tga
trunk/data/models/nexball/
trunk/data/models/nexball/ball.md3
trunk/data/qcsrc/server/nexball.qc
trunk/data/sound/nexball/
trunk/data/sound/nexball/bounce.ogg
trunk/data/sound/nexball/drop.ogg
trunk/data/sound/nexball/steal.ogg
trunk/data/textures/nexball/
trunk/data/textures/nexball/ball.tga
trunk/data/textures/nexball/ball_gloss.tga
trunk/data/textures/nexball/ball_norm.tga
trunk/misc/mediasource/graphics/sb-nexball-carrying.svg
Modified:
trunk/Docs/mapping.txt
trunk/data/defaultNexuiz.cfg
trunk/data/qcsrc/client/Defs.qc
trunk/data/qcsrc/client/Main.qc
trunk/data/qcsrc/client/main.qh
trunk/data/qcsrc/client/sbar.qc
trunk/data/qcsrc/common/constants.qh
trunk/data/qcsrc/common/mapinfo.qc
trunk/data/qcsrc/common/mapinfo.qh
trunk/data/qcsrc/common/util.qc
trunk/data/qcsrc/server/cl_client.qc
trunk/data/qcsrc/server/cl_physics.qc
trunk/data/qcsrc/server/cl_player.qc
trunk/data/qcsrc/server/cl_weapons.qc
trunk/data/qcsrc/server/clientcommands.qc
trunk/data/qcsrc/server/defs.qh
trunk/data/qcsrc/server/g_triggers.qc
trunk/data/qcsrc/server/g_world.qc
trunk/data/qcsrc/server/miscfunctions.qc
trunk/data/qcsrc/server/progs.src
trunk/data/qcsrc/server/scores_rules.qc
trunk/data/qcsrc/server/teamplay.qc
trunk/data/qcsrc/server/w_grenadelauncher.qc
trunk/data/scripts/entities.def
Log:
Nexball goes official :D
Also, removing the useless CSQC_REVISION checks.
Modified: trunk/Docs/mapping.txt
===================================================================
--- trunk/Docs/mapping.txt 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/Docs/mapping.txt 2009-04-22 17:52:53 UTC (rev 6568)
@@ -21,9 +21,9 @@
V Rune Match
-VI Assault
+VI Race
-VII Onslaught
+VII Nexball
Appendix A - Advanced mapinfo
@@ -362,7 +362,24 @@
such entities, delete the data/data/mapname.mapinfo file - or simply edit it to
add the "type race" line.
+=============
+=VI. Nexball=
+=============
+There are three required entities: ball_redgoal, ball_bluegoal, and one of ball_basketball
+or ball_football. Pay extra attention to the goals, as their names can be somewhat counter-
+intuitive: ball_redgoal will give a point to the red team when scored in, NOT to the blue team!
+
+There are also two other goal-like triggers, ball_fault and ball_bound, the first giving a point to
+the opposing team when the ball hits it, the second simply returning it. You can spawn the ball inside
+a goal-like trigger, this can be useful for basketball maps with separate teams and a common ball spawn.
+The different keys for the entities are documented in entities.def.
+
+The ball is affected by trigger_impulse, but not by trigger_push or teleporters.
+
+You should better avoid patches on the field, as collisions can sometimes get buggy on these.
+
+
===============================
=Appendix A - Advanced mapinfo=
===============================
Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/defaultNexuiz.cfg 2009-04-22 17:52:53 UTC (rev 6568)
@@ -459,6 +459,7 @@
seta g_runematch_point_limit -1 "Runematch point limit limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
seta g_keyhunt_point_limit -1 "Keyhunt point limit limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
seta g_race_laps_limit -1 "Race laps limit limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+seta g_nexball_goallimit -1 "Nexball goal limit limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
seta g_ctf_win_mode 0 "0: captures only, 1: captures, then points, 2: points only"
seta g_ctf_ignore_frags 0 "1: regular frags give no points"
@@ -646,6 +647,58 @@
// ready-restart it turns into a race. TODO not done yet (e.g. timing display)
set g_race_teams 0 "when 2, 3, or 4, the race is played as a team game (the team members can add up their laps)"
+// nexball
+set g_nexball 0
+
+set g_nexball_basketball_effects_default 8 "default: dim light. The original version used 1024 (fire) but it gives bad performance"
+set g_balance_nexball_primary_speed 1000 "launching speed"
+set g_balance_nexball_primary_refire 0.7 "launching refire"
+set g_balance_nexball_primary_animtime 0.3 "launching animtime"
+set g_balance_nexball_secondary_animtime 0.3 "launching animtime"
+set g_balance_nexball_secondary_speed 3000 "stealing projectile speed"
+set g_balance_nexball_secondary_lifetime 0.15 "stealing projectile lifetime"
+set g_balance_nexball_secondary_force 500 "stealing projectile force"
+set g_balance_nexball_secondary_refire 0.6 "stealing projectile refire"
+set g_balance_nexball_secondary_animtime 0.3 "stealing projectile animtime"
+
+// -1: MrBougo's first try, not very playable but working...
+// The ball gets the player's velocity * 1.5 + a vertical boost
+// 0: Revenant style
+// Player's velocity + a boost where he's looking at + a boost
+// perpendicularly to the first boost, that is upwards relatively
+// to the view angle
+// 1: MrBougo's modded Rev style 1
+// The 2nd Rev boost is always vertical
+// 2: MrBougo's modded Rev style 2
+// The 1st Rev boost is always horizontal
+// The 2nd Rev boost is always vertical
+set g_nexball_football_physics 2 "0: Revenant's original movement, 1: 0 but half independant of aiming height, 2: 1 fully independant, -1: first recode try"
+
+set g_nexball_football_boost_forward 100 "forward velocity boost when the ball is touched"
+set g_nexball_football_boost_up 200 "vertical velocity boost when the ball is touched"
+
+set g_nexball_basketball_delay_hold 20 "time before a player who caught the ball loses it (anti-ballcamp)"
+set g_nexball_basketball_delay_hold_forteam 60 "time before a ball reset when a team holds the ball for too long"
+set g_nexball_basketball_teamsteal 1 "1 to allow players to steal from teammates, 0 to disallow"
+
+set g_nexball_basketball_carrier_speed 0.9 "speed multiplier for the ballcarrier"
+
+set g_nexball_meter_period 1 "time to make a full cycle on the power meter"
+set g_nexball_basketball_meter 1 "use the power meter for basketball"
+set g_nexball_basketball_meter_minpower 0.5 "minimal multiplier to the launching speed when using the power meter"
+set g_nexball_basketball_meter_maxpower 1.2 "maximal multiplier to the launching speed when using the power meter"
+
+set g_nexball_delay_goal 3 "delay between a goal and a ball reset"
+set g_nexball_delay_idle 10 "maximal idle time before a reset"
+set g_nexball_delay_start 3 "time the ball stands on its spawn before being released"
+set g_nexball_delay_collect 0.5 "time before the same player can catch the ball he launched"
+
+set g_nexball_sound_bounce 1 "bouncing sound (0: off)"
+
+set g_nexball_basketball_trail 1 "1 to leave a trail"
+set g_nexball_football_trail 0 "1 to leave a trail"
+set g_nexball_trail_color 254 "1-256 for different colors (Quake palette, 254 is white)"
+
// server game balance settings
set g_balance_armor_regen 0
set g_balance_armor_rot 0.1
Added: trunk/data/gfx/sb_nexball_carrying.tga
===================================================================
(Binary files differ)
Property changes on: trunk/data/gfx/sb_nexball_carrying.tga
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/models/nexball/ball.md3
===================================================================
(Binary files differ)
Property changes on: trunk/data/models/nexball/ball.md3
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/data/qcsrc/client/Defs.qc
===================================================================
--- trunk/data/qcsrc/client/Defs.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/client/Defs.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -200,6 +200,9 @@
string race_othercheckpointenemy;
float sb_showscores_force;
+// Nexball
+float nb_pb_period;
+
// Spectating
float spectatee_status;
Modified: trunk/data/qcsrc/client/Main.qc
===================================================================
--- trunk/data/qcsrc/client/Main.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/client/Main.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -836,8 +836,6 @@
centerprint(strMessage);
}
-void CSQC_CheckRevision();
-
void Fog_Force()
{
// TODO somehow thwart prvm_globalset client ...
@@ -871,7 +869,7 @@
float i;
self.classname = "ent_client_init";
- csqc_revision = ReadShort();
+ nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
for(i = 0; i < 24; ++i)
weaponimpulse[i] = ReadByte() - 1;
@@ -883,7 +881,6 @@
strunzone(forcefog);
forcefog = strzone(ReadString());
- CSQC_CheckRevision();
if(!postinit)
PostInit();
}
@@ -1033,20 +1030,6 @@
return bHandled;
}
-// COMMIT-TODO: Update if necessare, before committing
-void CSQC_CheckRevision()
-{
- if(csqc_revision == CSQC_REVISION)
- {
- print("^2SVQC and CSQC revisions are compatible.\n");
- } else if(csqc_revision < CSQC_REVISION) {
- print("^1Your csprogs.dat (CSQC) version is newer than the one on the server.\n");
- } else if(csqc_revision > CSQC_REVISION) {
- print("^1Your csprogs.dat (CSQC) is too old for this server.\n");
- print("^1Please update to a newer version.\n");
- }
-}
-
string getcommandkey(string text, string command)
{
string keys;
Modified: trunk/data/qcsrc/client/main.qh
===================================================================
--- trunk/data/qcsrc/client/main.qh 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/client/main.qh 2009-04-22 17:52:53 UTC (rev 6568)
@@ -36,8 +36,6 @@
// --------------------------------------------------------------------------
// General stuff
-float csqc_revision;
-
float drawfont;
float postinit;
float gametype;
Modified: trunk/data/qcsrc/client/sbar.qc
===================================================================
--- trunk/data/qcsrc/client/sbar.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/client/sbar.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -13,6 +13,7 @@
void CSQC_kh_hud();
void CSQC_ctf_hud();
+void CSQC_nb_hud();
void MapVote_Draw();
void Sbar_FinaleOverlay()
{
@@ -2123,6 +2124,9 @@
} else if(gametype == GAME_CTF)
{
CSQC_ctf_hud();
+ } else if(gametype == GAME_NEXBALL)
+ {
+ CSQC_nb_hud();
}
}
Sbar_DrawCenterPrint();
@@ -2190,3 +2194,64 @@
drawpic(pos, "gfx/sb_flag_blue_shielded", '128 64 0', '1 1 1', sbar_alpha_fg, DRAWFLAG_NORMAL); break;
}
}
+
+//box style
+#define NBPB_SIZE '128 66 0'
+#define NBPB_BT 2 //thickness
+#define NBPB_BRGB '1 1 1'
+#define NBPB_BALPH 1 //alpha
+#define NBPB_BFLAG DRAWFLAG_NORMAL
+#define NBPB_IALPH 0.4
+#define NBPB_IFLAG DRAWFLAG_ADDITIVE
+#define NBPB_IRGB '0.7 0.1 0'
+
+void CSQC_nb_hud(void)
+{
+ float stat_items, nb_pb_starttime, dt, p;
+ vector pos;
+
+ stat_items = getstati(STAT_ITEMS);
+ nb_pb_starttime = getstatf(STAT_NB_METERSTART);
+
+ if(cvar("sbar_flagstatus_right"))
+ pos_x = vid_conwidth - 10 - sbar_x - 64;
+ else
+ pos_x = 10 - sbar_x;
+
+ pos_z = 0;
+
+ if(sbar_hudselector == 1)
+ pos_y = (vid_conheight - sbar_y) - cvar("sbar_flagstatus_pos") - 64;
+ else
+ pos_y = -117;
+
+ pos += sbar;
+ pos_y -= 1; //vertical margin to the picture
+
+ //Manage the progress bar if any
+ if (nb_pb_starttime > 0)
+ {
+ vector s;
+ dt = mod(time - nb_pb_starttime, nb_pb_period);
+ // one period of positive triangle
+ p = 2 * dt / nb_pb_period;
+ if (p > 1)
+ p = 2 - p;
+
+ s = NBPB_SIZE;
+ //Draw the filling
+ drawfill(pos, p * s_x * '1 0 0' + s_y * '0 1 0', NBPB_IRGB, NBPB_IALPH, NBPB_IFLAG);
+
+ //Draw the box
+ s = NBPB_SIZE;
+ drawline(NBPB_BT, pos , pos + '1 0 0' * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos , pos + '0 1 0' * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos + s, pos + '1 0 0' * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos + s, pos + '0 1 0' * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ }
+
+ pos_y += 1; //vertical margin to the picture
+
+ if (stat_items & IT_KEY1)
+ drawpic(pos, "gfx/sb_nexball_carrying", '128 64 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+}
Modified: trunk/data/qcsrc/common/constants.qh
===================================================================
--- trunk/data/qcsrc/common/constants.qh 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/common/constants.qh 2009-04-22 17:52:53 UTC (rev 6568)
@@ -36,6 +36,7 @@
const float GAME_ASSAULT = 9;
const float GAME_ONSLAUGHT = 10;
const float GAME_RACE = 11;
+const float GAME_NEXBALL = 12;
const float AS_STRING = 1;
const float AS_INT = 2;
@@ -248,6 +249,7 @@
const float STAT_PRESSED_KEYS = 42;
const float STAT_ALLOW_OLDNEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config
const float STAT_FUEL = 44;
+const float STAT_NB_METERSTART = 45;
const float CTF_STATE_ATTACK = 1;
const float CTF_STATE_DEFEND = 2;
const float CTF_STATE_COMMANDER = 3;
Modified: trunk/data/qcsrc/common/mapinfo.qc
===================================================================
--- trunk/data/qcsrc/common/mapinfo.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/common/mapinfo.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -399,6 +399,8 @@
MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ASSAULT;
else if(v == "onslaught_generator")
MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ONSLAUGHT;
+ else if(v == "ball_bluegoal")
+ MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_NEXBALL;
else if(v == "info_player_team1")
++spawnpoints;
else if(v == "info_player_team2")
@@ -521,19 +523,20 @@
float MapInfo_Type_FromString(string t)
{
- if (t == "dm") return MAPINFO_TYPE_DEATHMATCH;
- else if(t == "tdm") return MAPINFO_TYPE_TEAM_DEATHMATCH;
- else if(t == "dom") return MAPINFO_TYPE_DOMINATION;
- else if(t == "ctf") return MAPINFO_TYPE_CTF;
- else if(t == "rune") return MAPINFO_TYPE_RUNEMATCH;
- else if(t == "lms") return MAPINFO_TYPE_LMS;
- else if(t == "arena") return MAPINFO_TYPE_ARENA;
- else if(t == "kh") return MAPINFO_TYPE_KEYHUNT;
- else if(t == "as") return MAPINFO_TYPE_ASSAULT;
- else if(t == "ons") return MAPINFO_TYPE_ONSLAUGHT;
- else if(t == "race") return MAPINFO_TYPE_RACE;
- else if(t == "all") return MAPINFO_TYPE_ALL;
- else return 0;
+ if (t == "dm") return MAPINFO_TYPE_DEATHMATCH;
+ else if(t == "tdm") return MAPINFO_TYPE_TEAM_DEATHMATCH;
+ else if(t == "dom") return MAPINFO_TYPE_DOMINATION;
+ else if(t == "ctf") return MAPINFO_TYPE_CTF;
+ else if(t == "rune") return MAPINFO_TYPE_RUNEMATCH;
+ else if(t == "lms") return MAPINFO_TYPE_LMS;
+ else if(t == "arena") return MAPINFO_TYPE_ARENA;
+ else if(t == "kh") return MAPINFO_TYPE_KEYHUNT;
+ else if(t == "as") return MAPINFO_TYPE_ASSAULT;
+ else if(t == "ons") return MAPINFO_TYPE_ONSLAUGHT;
+ else if(t == "race") return MAPINFO_TYPE_RACE;
+ else if(t == "nexball") return MAPINFO_TYPE_NEXBALL;
+ else if(t == "all") return MAPINFO_TYPE_ALL;
+ else return 0;
}
// load info about a map by name into the MapInfo_Map_* globals
@@ -611,6 +614,7 @@
if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ASSAULT) fputs(fh, "type as 20\n");
if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE) fputs(fh, "type race 5 20 15\n");
if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ONSLAUGHT) fputs(fh, "type ons 20\n");
+ if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_NEXBALL) fputs(fh, "type nexball 5 20\n");
fh2 = fopen(strcat("scripts/", pFilename, ".arena"), FILE_READ);
if(fh2 >= 0)
@@ -856,7 +860,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") || cvar("g_race")))
+ if(!(cvar("g_lms") || cvar("g_instagib") || cvar("g_minstagib") || cvar("g_nixnex") || cvar("g_rocketarena") || !cvar("g_pickup_items") || cvar("g_race") || cvar("g_nexball")))
req |= MAPINFO_FEATURE_WEAPONS;
return req;
}
@@ -883,6 +887,8 @@
return MAPINFO_TYPE_ONSLAUGHT;
else if(cvar("g_race"))
return MAPINFO_TYPE_RACE;
+ else if(cvar("g_nexball"))
+ return MAPINFO_TYPE_NEXBALL;
else
return MAPINFO_TYPE_DEATHMATCH;
}
@@ -939,6 +945,7 @@
cvar_set("g_assault", (t == MAPINFO_TYPE_ASSAULT) ? "1" : "0");
cvar_set("g_onslaught", (t == MAPINFO_TYPE_ONSLAUGHT) ? "1" : "0");
cvar_set("g_race", (t == MAPINFO_TYPE_RACE) ? "1" : "0");
+ cvar_set("g_nexball", (t == MAPINFO_TYPE_NEXBALL) ? "1" : "0");
}
void MapInfo_LoadMap(string s)
Modified: trunk/data/qcsrc/common/mapinfo.qh
===================================================================
--- trunk/data/qcsrc/common/mapinfo.qh 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/common/mapinfo.qh 2009-04-22 17:52:53 UTC (rev 6568)
@@ -9,6 +9,7 @@
float MAPINFO_TYPE_LMS = 256;
float MAPINFO_TYPE_ARENA = 512;
float MAPINFO_TYPE_KEYHUNT = 1024;
+float MAPINFO_TYPE_NEXBALL = 2048;
float MAPINFO_TYPE_ALL = 65535; // this has to include all above bits
float MAPINFO_FEATURE_WEAPONS = 1; // not defined for minstagib-only maps
Modified: trunk/data/qcsrc/common/util.qc
===================================================================
--- trunk/data/qcsrc/common/util.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/common/util.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -426,6 +426,7 @@
else if (g == GAME_ONSLAUGHT) return "ons";
else if (g == GAME_ASSAULT) return "as";
else if (g == GAME_RACE) return "race";
+ else if (g == GAME_NEXBALL) return "nexball";
return "dm";
}
Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/cl_client.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -489,6 +489,8 @@
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
+ if(self.ballcarried)
+ DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity);
WaypointSprite_PlayerDead();
@@ -802,6 +804,8 @@
self.hook_time = 0;
self.dmg_team = 0;
+ self.metertime = 0;
+
self.runes = 0;
self.deadflag = DEAD_NO;
@@ -908,7 +912,7 @@
{
float i;
WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
- WriteShort(MSG_ENTITY, CSQC_REVISION);
+ WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
for(i = 1; i <= 24; ++i)
WriteByte(MSG_ENTITY, (get_weaponinfo(i)).impulse + 1);
WriteCoord(MSG_ENTITY, hook_shotorigin_x);
@@ -1329,8 +1333,6 @@
if(clienttype(self) == CLIENTTYPE_REAL)
{
- sprint(self, strcat("nexuiz-csqc protocol ", ftos(CSQC_REVISION), "\n"));
-
if(cvar("g_bugrigs"))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
@@ -1387,6 +1389,8 @@
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
+ if(self.ballcarried)
+ DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity);
// Here, everything has been done that requires this player to be a client.
@@ -1895,6 +1899,7 @@
self.health = spectatee.health;
self.impulse = 0;
self.items = spectatee.items;
+ self.metertime = spectatee.metertime;
self.strength_finished = spectatee.strength_finished;
self.invincible_finished = spectatee.invincible_finished;
self.pressedkeys = spectatee.pressedkeys;
@@ -2160,6 +2165,7 @@
=============
*/
void() ctf_setstatus;
+void() nexball_setstatus;
void PlayerPreThink (void)
{
self.stat_sys_ticrate = cvar("sys_ticrate");
@@ -2400,6 +2406,7 @@
ctf_setstatus();
kh_setstatus();
+ nexball_setstatus();
self.dmg_team = max(0, self.dmg_team - cvar("g_teamdamage_resetspeed") * frametime);
Modified: trunk/data/qcsrc/server/cl_physics.qc
===================================================================
--- trunk/data/qcsrc/server/cl_physics.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/cl_physics.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -436,6 +436,11 @@
maxspd_mod = cvar("g_minstagib_speed_moverate");
}
+ if(g_nexball && self.ballcarried)
+ {
+ maxspd_mod = cvar("g_nexball_basketball_carrier_speed");
+ }
+
swampspd_mod = 1;
if(self.in_swamp) {
swampspd_mod = self.swamp_slowdown; //cvar("g_balance_swamp_moverate");
Modified: trunk/data/qcsrc/server/cl_player.qc
===================================================================
--- trunk/data/qcsrc/server/cl_player.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/cl_player.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -429,6 +429,8 @@
else
DropFlag(self.flagcarried, world, attacker);
}
+ if(self.ballcarried)
+ DropBall(self.ballcarried, self.origin, self.velocity);
Portal_ClearAllLater(self);
// clear waypoints
WaypointSprite_PlayerDead();
Modified: trunk/data/qcsrc/server/cl_weapons.qc
===================================================================
--- trunk/data/qcsrc/server/cl_weapons.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/cl_weapons.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -259,6 +259,8 @@
return;
if (g_nixnex)
return;
+ if (g_nexball && w == WEP_GRENADE_LAUNCHER)
+ return;
if (!cvar("g_pickup_items"))
return;
if(!W_IsWeaponThrowable(w))
Modified: trunk/data/qcsrc/server/clientcommands.qc
===================================================================
--- trunk/data/qcsrc/server/clientcommands.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/clientcommands.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -178,6 +178,8 @@
if(self.classname == "player" && cvar("sv_spectate") == 1) {
if(self.flagcarried)
DropFlag(self.flagcarried, world, world);
+ if(self.ballcarried)
+ DropBall(self.ballcarried, self.origin, self.velocity);
kh_Key_DropAll(self, TRUE);
WaypointSprite_PlayerDead();
self.classname = "observer";
Modified: trunk/data/qcsrc/server/defs.qh
===================================================================
--- trunk/data/qcsrc/server/defs.qh 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/defs.qh 2009-04-22 17:52:53 UTC (rev 6568)
@@ -19,7 +19,7 @@
float ctf_score_value(string parameter);
-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_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_lms, g_runematch, g_race, g_nexball;
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_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
float g_warmup_limit;
float g_warmup_allguns;
@@ -342,6 +342,7 @@
float startitem_failed;
void DropFlag(entity flag, entity penalty_receiver, entity attacker);
+void DropBall(entity ball, vector org, vector vel);
void DropAllRunes(entity pl);
@@ -537,6 +538,11 @@
.string target4;
.float trigger_reverse;
+// Nexball
+.entity ballcarried;
+.float metertime;
+float g_nexball_meter_period;
+
void SUB_DontUseTargets();
void SUB_UseTargets();
Modified: trunk/data/qcsrc/server/g_triggers.qc
===================================================================
--- trunk/data/qcsrc/server/g_triggers.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/g_triggers.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -1098,6 +1098,8 @@
if (other.classname != "plasma_prim")
if (other.classname != "plasma_chain")
if (other.classname != "droppedweapon")
+ if (other.classname != "ball_basketball")
+ if (other.classname != "ball_football")
return;
if (other.deadflag && other.iscreature)
@@ -1147,6 +1149,8 @@
if (other.classname != "plasma_prim")
if (other.classname != "plasma_chain")
if (other.classname != "droppedweapon")
+ if (other.classname != "ball_basketball")
+ if (other.classname != "ball_football")
return;
if (other.deadflag && other.iscreature)
@@ -1184,6 +1188,8 @@
if (other.classname != "plasma_prim")
if (other.classname != "plasma_chain")
if (other.classname != "droppedweapon")
+ if (other.classname != "ball_basketball")
+ if (other.classname != "ball_football")
return;
if (other.deadflag && other.iscreature)
Modified: trunk/data/qcsrc/server/g_world.qc
===================================================================
--- trunk/data/qcsrc/server/g_world.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/g_world.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -1669,7 +1669,7 @@
limit = -limit;
}
- if(g_dm || g_tdm || g_arena || (g_race && !g_race_qualifying))
+ if(g_dm || g_tdm || g_arena || (g_race && !g_race_qualifying) || g_nexball)
// these modes always score in increments of 1, thus this makes sense
{
if(leaderfrags != WinningConditionHelper_topscore)
Modified: trunk/data/qcsrc/server/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/server/miscfunctions.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/miscfunctions.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -238,7 +238,7 @@
if(!self.cnt)
self.cnt = 1;
- if(g_ctf || g_assault || g_onslaught || g_domination)
+ if(g_ctf || g_assault || g_onslaught || g_domination || g_nexball)
if(self.team)
have_team_spawns = 1;
@@ -892,6 +892,9 @@
t += (i == WEP_HOOK);
}
+ if(g_nexball && i == WEP_GRENADE_LAUNCHER)
+ t=1;
+
if(t)
{
start_weapons |= e.weapons;
Added: trunk/data/qcsrc/server/nexball.qc
===================================================================
--- trunk/data/qcsrc/server/nexball.qc (rev 0)
+++ trunk/data/qcsrc/server/nexball.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -0,0 +1,667 @@
+//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
+#define BALL_EFFECTMASK 1229
+#define BALL_MINS '-16 -16 -16' // The model is 24*24*24
+#define BALL_MAXS '16 16 16'
+#define BALL_ATTACHORG '3 0 16'
+#define BALL_FOOT 1
+#define BALL_BASKET 2
+#define GOAL_TOUCHPLAYER 1
+#define CVTOV(s) s = cvar( #s )
+
+float g_nexball_football_boost_forward;
+float g_nexball_football_boost_up;
+float g_nexball_football_physics;
+float g_nexball_delay_idle;
+float g_nexball_basketball_delay_hold;
+float g_nexball_basketball_delay_hold_forteam;
+float g_nexball_basketball_effects_default;
+float g_nexball_basketball_teamsteal;
+float balls;
+float ball_scale;
+
+.float teamtime;
+
+void nb_init() // Called early (worldspawn stage)
+{
+ CVTOV(g_nexball_meter_period); //sent with the client init entity
+ if (g_nexball_meter_period <= 0)
+ g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
+ g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
+ addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
+
+ // General settings
+ CVTOV(g_nexball_football_boost_forward); //100
+ CVTOV(g_nexball_football_boost_up); //200
+ CVTOV(g_nexball_delay_idle); //10
+ CVTOV(g_nexball_football_physics); //0
+}
+
+void ResetBall();
+
+void LogNB(string mode, entity actor)
+{
+ string s;
+ if(!cvar("sv_eventlog"))
+ return;
+ s = strcat(":nexball:", mode);
+ if(actor != world)
+ s = strcat(s, ":", ftos(actor.playerid));
+ GameLogEcho(s);
+}
+
+void ball_restart (void)
+{
+ if(self.owner)
+ DropBall(self, self.owner.origin, '0 0 0');
+ ResetBall();
+}
+
+void nexball_setstatus (void)
+{
+ local entity oldself;
+ if (!g_nexball)
+ return;
+ if (self.ballcarried)
+ {
+ if (self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
+ {
+ bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
+ oldself = self;
+ self = self.ballcarried;
+ DropBall(self, self.owner.origin, '0 0 0');
+ ResetBall();
+ self = oldself;
+ } else
+ self.items |= IT_KEY1;
+ }
+}
+
+void relocate_nexball (void)
+{
+ tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, TRUE, self);
+ if (trace_startsolid)
+ {
+ vector o;
+ o = self.origin;
+ if(!move_out_of_solid(self))
+ objerror("could not get out of solid at all!");
+ print("^1NOTE: this map needs FIXING. ", self.classname, " 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));
+ print(" ", ftos(self.origin_z - o_z), "'\n");
+ self.origin = o;
+ }
+}
+
+void basketball_touch();
+void football_touch();
+
+void DropOwner (void)
+{
+ local entity ownr;
+ ownr = self.owner;
+ DropBall(self, ownr.origin, ownr.velocity);
+ makevectors(ownr.v_angle_y * '0 1 0');
+ ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
+ ownr.flags &~= FL_ONGROUND;
+}
+
+void DropBall (entity ball, vector org, vector vel)
+{
+ ball.effects |= g_nexball_basketball_effects_default;
+ ball.effects &~= EF_NOSHADOW;
+ ball.owner.effects &~= g_nexball_basketball_effects_default; // this may be problematic.
+
+ setattachment(ball, world, "");
+ setorigin (ball, org);
+ ball.movetype = MOVETYPE_BOUNCE;
+ ball.flags &~= FL_ONGROUND;
+ ball.scale = ball_scale;
+ ball.velocity = vel;
+ ball.ctf_droptime = time;
+ ball.touch = basketball_touch;
+ ball.think = ResetBall;
+ ball.nextthink = min(time + g_nexball_delay_idle, ball.teamtime);
+
+ if (ball.owner.metertime)
+ {
+ ball.owner.metertime = 0;
+ ball.owner.weaponentity.state = WS_READY;
+ }
+
+ ball.owner.ballcarried = world;
+ ball.owner = world;
+}
+
+void InitBall (void)
+{
+ if (gameover) return;
+ self.flags &~= FL_ONGROUND;
+ self.movetype = MOVETYPE_BOUNCE;
+ if (self.classname == "ball_basketball")
+ self.touch = basketball_touch;
+ else if (self.classname == "ball_football")
+ self.touch = football_touch;
+ self.cnt = 0;
+ self.think = ResetBall;
+ self.nextthink = time + g_nexball_delay_idle + 3;
+ self.teamtime = 0;
+ self.pusher = world;
+ self.team = FALSE;
+ sound (self, CHAN_PROJECTILE, self.noise1, VOL_BASE, ATTN_NORM);
+ LogNB("init", world);
+}
+
+void ResetBall (void)
+{
+ if (self.cnt < 2) { // step 1
+ if (time == self.teamtime)
+ bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
+ self.touch = SUB_Null;
+ self.movetype = MOVETYPE_NOCLIP;
+ self.velocity = '0 0 0'; // just in case?
+ if(!self.cnt)
+ LogNB("resetidle", world);
+ self.cnt = 2;
+ self.nextthink = time;
+ } else if (self.cnt < 4) { // step 2 and 3
+// dprint("Step ", ftos(self.cnt), ": Calculated velocity: ", vtos(self.spawnorigin - self.origin), ", time: ", ftos(time), "\n");
+ self.velocity = (self.spawnorigin - self.origin) * (self.cnt - 1); // 1 or 0.5 second movement
+ self.nextthink = time + 0.5;
+ self.cnt += 1;
+ } else { // step 4
+// dprint("Step 4: time: ", ftos(time), "\n");
+ if (vlen(self.origin - self.spawnorigin) > 10) // should not happen anymore
+ dprint("The ball moved too far away from its spawn origin.\nOffset: ",
+ vtos(self.origin - self.spawnorigin), " Velocity: ", vtos(self.velocity), "\n");
+ self.velocity = '0 0 0';
+ setorigin(self, self.spawnorigin); // make sure it's positioned correctly anyway
+ self.movetype = MOVETYPE_NONE;
+ self.think = InitBall;
+ self.nextthink = max(time, game_starttime) + cvar("g_nexball_delay_start");
+ }
+}
+
+void football_touch (void)
+{
+ if (other.solid == SOLID_BSP) {
+ if (time > self.lastground + 0.1)
+ {
+ sound (self, CHAN_PROJECTILE, self.noise, VOL_BASE, ATTN_NORM);
+ self.lastground = time;
+ }
+ if (vlen(self.velocity) && !self.cnt)
+ self.nextthink = time + g_nexball_delay_idle;
+ return;
+ }
+ if (other.classname != "player")
+ return;
+ if (other.health < 1)
+ return;
+ if (!self.cnt)
+ self.nextthink = time + g_nexball_delay_idle;
+
+ self.pusher = other;
+ self.team = other.team;
+
+ if (g_nexball_football_physics == -1) { // MrBougo try 1, before decompiling Rev's original
+ if (vlen(other.velocity))
+ self.velocity = other.velocity * 1.5 + '0 0 1' * g_nexball_football_boost_up;
+ } else if (g_nexball_football_physics == 1) { // MrBougo's modded Rev style: partially independant of the height of the aiming point
+ makevectors(other.v_angle);
+ self.velocity = other.velocity + v_forward * g_nexball_football_boost_forward + '0 0 1' * g_nexball_football_boost_up;
+ } else if (g_nexball_football_physics == 2) { // 2nd mod try: totally independant. Really playable!
+ makevectors(other.v_angle_y * '0 1 0');
+ self.velocity = other.velocity + v_forward * g_nexball_football_boost_forward + v_up * g_nexball_football_boost_up;
+ } else { // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
+ makevectors(other.v_angle);
+ self.velocity = other.velocity + v_forward * g_nexball_football_boost_forward + v_up * g_nexball_football_boost_up;
+ }
+ self.avelocity = -250 * v_forward; // maybe there is a way to make it look better?
+}
+
+void basketball_touch (void)
+{
+ if (other.ballcarried)
+ {
+ football_touch();
+ return;
+ }
+ if (!self.cnt && other.classname == "player" && (other.playerid != self.dropperid || time > self.ctf_droptime + cvar("g_nexball_delay_collect"))) {
+ if (other.health <= 0)
+ return;
+ LogNB("caught", other);
+
+ if (self.team != other.team)
+ self.teamtime = time + g_nexball_basketball_delay_hold_forteam;
+
+ self.owner = self.pusher = other;
+ self.team = other.team;
+ other.ballcarried = self;
+ other.effects = other.effects | g_nexball_basketball_effects_default;
+ self.effects &~= g_nexball_basketball_effects_default;
+ self.effects |= EF_NOSHADOW;
+ self.scale = 1; // scale down.
+ self.dropperid = other.playerid;
+ setattachment(self, other, "");
+ setorigin(self, BALL_ATTACHORG);
+ self.velocity = '0 0 0';
+ self.movetype = MOVETYPE_NONE;
+ self.touch = SUB_Null;
+ if (g_nexball_basketball_delay_hold)
+ {
+ self.think = DropOwner;
+ self.nextthink = time + g_nexball_basketball_delay_hold;
+ }
+ } else if (other.solid == SOLID_BSP) {
+ sound (self, CHAN_PROJECTILE, self.noise, VOL_BASE, ATTN_NORM);
+ if (vlen(self.velocity) && !self.cnt)
+ self.nextthink = min(time + g_nexball_delay_idle, self.teamtime);
+ }
+}
+
+void ReturnTouch (void)
+{
+ string othername;
+ entity tempother;
+ tempother = other;
+
+ if (gameover) return;
+ if ((self.spawnflags & GOAL_TOUCHPLAYER) && tempother.ballcarried)
+ tempother = tempother.ballcarried; // Can't drop here yet because of EXACTTRIGGER
+ if (tempother.classname != "ball_basketball")
+ if (tempother.classname != "ball_football")
+ return;
+ if (tempother.cnt)
+ return;
+ EXACTTRIGGER_TOUCH;
+ other = tempother;
+
+ if (other.owner)
+ {
+ othername = other.owner.netname;
+ DropBall(other, other.owner.origin, '0 0 0');
+ }
+ else
+ othername = "The ball";
+
+ LogNB("out", other.pusher);
+ if (self.spawnflags & GOAL_TOUCHPLAYER)
+ bprint(othername, "^7 went out of bounds.\n");
+ else
+ bprint("The ball was returned.\n");
+ sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NONE);
+
+ other.cnt = 1;
+ other.think = ResetBall;
+ if (other.classname == "ball_basketball")
+ other.touch = football_touch;
+ other.nextthink = time + 1.5;
+}
+
+void GoalTouch (void)
+{
+ string othername;
+ entity tempother;
+ float isclient;
+ tempother = other; // EXACTTRIGGER uses "other"
+
+ if (gameover) return;
+ if ((self.spawnflags & GOAL_TOUCHPLAYER) && tempother.ballcarried)
+ tempother = tempother.ballcarried; // Can't drop here yet because of EXACTTRIGGER
+ if (tempother.classname != "ball_basketball")
+ if (tempother.classname != "ball_football")
+ return;
+ if (!tempother.pusher || tempother.cnt)
+ return;
+ EXACTTRIGGER_TOUCH;
+ other = tempother;
+
+ isclient = other.pusher.flags & FL_CLIENT;
+
+ if (isclient)
+ othername = other.pusher.netname;
+ else
+ othername = "Someone (?)";
+
+ if (self.classname == "ball_fault") { // FIXME?: this is ugly
+ if (other.team == COLOR_TEAM1) self.team = COLOR_TEAM2;
+ else if (other.team == COLOR_TEAM2) self.team = COLOR_TEAM1;
+ else self.team = FALSE;
+
+ if (isclient)
+ PlayerScore_Add(other.pusher, SP_NEXBALL_OWNGOALS, 1);
+ if (self.team)
+ {
+ bprint(ColoredTeamName(self.team), " gets awarded 1 point for ", othername, "^7's silliness.\n");
+ LogNB("fault-score", other.pusher);
+ }
+ else
+ {
+ bprint("The ball was reset.\n");
+ LogNB("fault-reset", other.pusher);
+ }
+ } else if (other.team == self.team) { // the goal's .team is set to the team it gives points to
+ if (isclient)
+ PlayerScore_Add(other.pusher, SP_NEXBALL_GOALS, 1);
+ bprint("Goaaaaal! ", othername, "^7 scored a point for the ", ColoredTeamName(self.team), ".\n");
+ LogNB("goal", other.pusher);
+ } else if (other.team) {
+ if (isclient)
+ PlayerScore_Add(other.pusher, SP_NEXBALL_OWNGOALS, 1);
+ bprint("Boo! ", othername, "^7 scored a point for the opposing ", ColoredTeamName(self.team), ".\n");
+ LogNB("owngoal", other.pusher);
+ } else {
+ bprint(othername, "^7 scored a point for the ", ColoredTeamName(self.team), ".\n"); //Should not happen
+ LogNB("goal-noteam", other.pusher);
+ }
+ sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NONE);
+
+ if (self.team)
+ TeamScore_AddToTeam(self.team, ST_NEXBALL_GOALS, 1);
+
+ if (other.owner) // Happens on spawnflag GOAL_TOUCHPLAYER
+ DropBall(other, other.owner.origin, other.owner.velocity);
+ other.cnt = 1;
+ other.think = ResetBall;
+ if (other.classname == "ball_basketball")
+ other.touch = football_touch; // better than SUB_Null: football control until the ball gets reset
+ other.nextthink = time + cvar("g_nexball_delay_goal");
+}
+
+//=======================//
+// spawnfuncs //
+//=======================//
+
+void SpawnBall (void)
+{
+ if(!g_nexball) { remove(self); return; }
+
+ if (!self.model) {
+ self.model = "models/nexball/ball.md3";
+ self.scale = 1.3;
+ }
+
+ precache_model (self.model);
+ setmodel (self, self.model);
+ setsize (self, BALL_MINS, BALL_MAXS);
+ ball_scale = self.scale;
+
+ relocate_nexball();
+ self.spawnorigin = self.origin;
+
+ self.effects = self.effects | EF_LOWPRECISION;
+
+ if (cvar(strcat("g_nex", self.classname, "_trail")))
+ {
+ self.glow_color = cvar("g_nexball_trail_color");
+ self.glow_trail = TRUE;
+ }
+
+ self.movetype = MOVETYPE_FLY;
+
+ if (!cvar("g_nexball_sound_bounce"))
+ self.noise = "";
+ else if (!self.noise)
+ self.noise = "sound/nexball/bounce.ogg";
+ //bounce sound placeholder (FIXME)
+ if (!self.noise1)
+ self.noise1 = "sound/nexball/drop.ogg";
+ //ball drop sound placeholder (FIXME)
+ if (!self.noise2)
+ self.noise2 = "sound/nexball/steal.ogg";
+ //stealing sound placeholder (FIXME)
+ if (self.noise) precache_sound (self.noise);
+ precache_sound (self.noise1);
+ precache_sound (self.noise2);
+
+ self.reset = ball_restart;
+ self.think = InitBall;
+ self.nextthink = game_starttime + cvar("g_nexball_delay_start");
+}
+
+void spawnfunc_ball_basketball (void)
+{
+ if(!balls & BALL_BASKET)
+ {
+ CVTOV(g_nexball_basketball_effects_default);
+ CVTOV(g_nexball_basketball_delay_hold);
+ CVTOV(g_nexball_basketball_delay_hold_forteam);
+ CVTOV(g_nexball_basketball_teamsteal);
+ g_nexball_basketball_effects_default = g_nexball_basketball_effects_default & BALL_EFFECTMASK;
+ }
+ if (!self.effects)
+ self.effects = g_nexball_basketball_effects_default;
+ self.solid = SOLID_TRIGGER;
+
+ balls |= BALL_BASKET;
+
+ SpawnBall();
+}
+
+void spawnfunc_ball_football (void)
+{
+ self.solid = SOLID_TRIGGER;
+
+ balls |= BALL_FOOT;
+
+ SpawnBall();
+}
+
+void spawnfunc_ball (void)
+{
+ self.classname = "ball_football";
+ spawnfunc_ball_football();
+}
+
+// The "red goal" is defended by blue team. A ball in there counts as a point for red.
+void spawnfunc_ball_redgoal (void)
+{
+ if(!g_nexball) { remove(self); return; }
+ //COLOR_TEAM1 is red
+ EXACTTRIGGER_INIT;
+ self.team = COLOR_TEAM1;
+ if (!self.noise)
+ self.noise = "ctf/redcapture.wav";
+ precache_sound(self.noise);
+ self.touch = GoalTouch;
+}
+
+//Same comment.
+void spawnfunc_ball_bluegoal (void)
+{
+ if(!g_nexball) { remove(self); return; }
+ EXACTTRIGGER_INIT;
+ self.team = COLOR_TEAM2;
+ if (!self.noise)
+ self.noise = "ctf/bluecapture.wav";
+ precache_sound(self.noise);
+ self.touch = GoalTouch;
+}
+
+void spawnfunc_ball_fault (void)
+{
+ if(!g_nexball) { remove(self); return; }
+ EXACTTRIGGER_INIT;
+ if (!self.noise)
+ self.noise = "misc/typehit.wav";
+ precache_sound(self.noise);
+ self.touch = GoalTouch;
+}
+
+void spawnfunc_ball_bound (void)
+{
+ if(!g_nexball) { remove(self); return; }
+ EXACTTRIGGER_INIT;
+ if (!self.noise)
+ self.noise = "misc/typehit.wav";
+ precache_sound(self.noise);
+ self.touch = ReturnTouch;
+}
+
+
+//=======================//
+// Weapon code //
+//=======================//
+
+void W_Nexball_Touch (void)
+{
+ local entity ball, attacker;
+ attacker = self.owner;
+
+ PROJECTILE_TOUCH;
+ if(attacker.team != other.team || g_nexball_basketball_teamsteal)
+ if((ball = other.ballcarried))
+ {
+ other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * cvar("g_balance_nexball_secondary_force");
+ other.flags &~= FL_ONGROUND;
+ if(!attacker.ballcarried)
+ {
+ other.effects &~= g_nexball_basketball_effects_default;
+ other.ballcarried = world;
+
+ if (g_nexball_basketball_delay_hold)
+ {
+ ball.think = DropOwner;
+ ball.nextthink = time + g_nexball_basketball_delay_hold;
+ }
+
+ attacker.effects = attacker.effects | g_nexball_basketball_effects_default;
+ attacker.ballcarried = ball;
+ if (other.metertime)
+ {
+ other.metertime = 0;
+ other.weaponentity.state = WS_READY;
+ }
+
+ setattachment(ball, attacker, "");
+ ball.owner = ball.pusher = attacker;
+ ball.team = attacker.team;
+ ball.dropperid = attacker.playerid;
+
+ if (other.team != attacker.team)
+ ball.teamtime = time + g_nexball_basketball_delay_hold_forteam;
+
+ LogNB("stole", attacker);
+ sound (other, CHAN_AUTO, ball.noise2, VOL_BASE, ATTN_NORM);
+ }
+ }
+ remove(self);
+}
+
+void W_Nexball_Attack (float t)
+{
+ local entity ball;
+ local float mul, mi, ma;
+ if (!(ball = self.ballcarried))
+ return;
+
+ W_SetupShot (self, FALSE, 4, "weapons/grenade_fire.wav");
+ tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world);
+ if(trace_startsolid)
+ {
+ if(self.metertime)
+ self.metertime = 0; // Shot failed, hide the power meter
+ return;
+ }
+
+ //Calculate multiplier
+ if (t < 0)
+ mul = 1;
+ else
+ {
+ mi = cvar("g_nexball_basketball_meter_minpower");
+ ma = max(mi, cvar("g_nexball_basketball_meter_maxpower")); // avoid confusion
+ //One triangle wave period with 1 as max
+ mul = 2 * mod(t, g_nexball_meter_period) / g_nexball_meter_period;
+ if (mul > 1)
+ mul = 2 - mul;
+ mul = mi + (ma - mi) * mul; // range from the minimal power to the maximal power
+ }
+ DropBall (ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * cvar("g_balance_nexball_primary_speed") * mul));
+ //TODO: use the speed_up cvar too ??
+}
+
+void W_Nexball_Attack2 (void)
+{
+ local entity missile;
+ if (!(balls & BALL_BASKET))
+ return;
+ W_SetupShot (self, FALSE, 2, "weapons/grenade_fire.wav");
+ pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+ missile = spawn ();
+
+ missile.owner = self;
+ missile.classname = "ballstealer";
+
+ missile.movetype = MOVETYPE_FLY;
+ missile.solid = SOLID_BBOX;
+
+ setmodel (missile, "models/elaser.mdl"); // precision set below
+ setsize (missile, '0 0 0', '0 0 0');
+ setorigin (missile, w_shotorg);
+
+ missile.velocity = w_shotdir * cvar("g_balance_nexball_secondary_speed");
+ W_SetupProjectileVelocity(missile);
+ missile.angles = vectoangles (missile.velocity);
+ missile.touch = W_Nexball_Touch;
+ missile.think = SUB_Remove;
+ missile.nextthink = time + cvar("g_balance_nexball_secondary_lifetime"); //FIXME: use a distance instead?
+
+ missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION;
+ missile.flags = FL_PROJECTILE;
+}
+
+float w_nexball_weapon(float req)
+{
+ if (req == WR_THINK)
+ {
+ if (self.BUTTON_ATCK)
+ if (weapon_prepareattack(0, cvar("g_balance_nexball_primary_refire")))
+ if (cvar("g_nexball_basketball_meter"))
+ {
+ if (self.ballcarried && !self.metertime)
+ self.metertime = time;
+ else
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_nexball_primary_animtime"), w_ready);
+ }
+ else
+ {
+ W_Nexball_Attack(-1);
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_nexball_primary_animtime"), w_ready);
+ }
+ if (self.BUTTON_ATCK2)
+ if (weapon_prepareattack(1, cvar("g_balance_nexball_secondary_refire")))
+ {
+ W_Nexball_Attack2();
+ weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_nexball_secondary_animtime"), w_ready);
+ }
+
+ if (!self.BUTTON_ATCK && self.metertime && self.ballcarried)
+ {
+ W_Nexball_Attack(time - self.metertime);
+ // DropBall or stealing will set metertime back to 0
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_nexball_primary_animtime"), w_ready);
+ }
+ }
+ else if (req == WR_PRECACHE)
+ {
+ precache_model ("models/weapons/g_gl.md3");
+ precache_model ("models/weapons/v_gl.md3");
+ precache_model ("models/weapons/h_gl.dpm");
+ precache_model ("models/elaser.mdl");
+ precache_sound ("weapons/grenade_fire.wav");
+ }
+ else if (req == WR_SETUP)
+ weapon_setup(WEP_GRENADE_LAUNCHER);
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ w_deathtypestring = "is a weirdo";
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ w_deathtypestring = "got killed by #'s black magic";
+ }
+ // No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE
+ return TRUE;
+}
Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/progs.src 2009-04-22 17:52:53 UTC (rev 6568)
@@ -120,6 +120,7 @@
ctf.qc
domination.qc
mode_onslaught.qc
+nexball.qc
g_hook.qc
t_swamp.qc
Modified: trunk/data/qcsrc/server/scores_rules.qc
===================================================================
--- trunk/data/qcsrc/server/scores_rules.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/scores_rules.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -172,3 +172,16 @@
ScoreInfo_SetLabel_PlayerScore(SP_ASSAULT_OBJECTIVES, "objectives", SFL_SORT_PRIO_PRIMARY);
ScoreRules_basics_end();
}
+
+// Nexball stuff
+#define ST_NEXBALL_GOALS 1
+#define SP_NEXBALL_GOALS 4
+#define SP_NEXBALL_OWNGOALS 5
+void ScoreRules_nexball()
+{
+ ScoreRules_basics(2, 0, 0, TRUE);
+ ScoreInfo_SetLabel_TeamScore ( ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+ ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+ ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_OWNGOALS, "owngoals", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
+ ScoreRules_basics_end();
+}
Modified: trunk/data/qcsrc/server/teamplay.qc
===================================================================
--- trunk/data/qcsrc/server/teamplay.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/teamplay.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -69,6 +69,7 @@
void ctf_init();
void runematch_init();
void tdm_init();
+void nb_init();
void entcs_init();
void LogTeamchange(entity pl)
@@ -119,6 +120,7 @@
found += (g_assault = (!found && (prev != GAME_ASSAULT) && cvar("g_assault")));
found += (g_onslaught = (!found && (prev != GAME_ONSLAUGHT) && cvar("g_onslaught")));
found += (g_race = (!found && (prev != GAME_RACE) && cvar("g_race")));
+ found += (g_nexball = (!found && (prev != GAME_NEXBALL) && cvar("g_nexball")));
if(found)
break;
@@ -322,6 +324,16 @@
ScoreRules_race();
}
+ if(g_nexball)
+ {
+ game = GAME_NEXBALL;
+ gamemode_name = "Nexball";
+ fraglimit_override = cvar("g_nexball_goallimit");
+ nb_init();
+ ActivateTeamplay();
+ ScoreRules_nexball();
+ }
+
if(teams_matter)
entcs_init();
@@ -560,9 +572,9 @@
teament_name = "ctf_team";
else if(g_tdm)
teament_name = "tdm_team";
- else if(g_assault)
+ else if(g_assault || g_nexball)
{
- c1 = c2 = 0; // Assault always has 2 teams
+ c1 = c2 = 0; // Assault and nexball always have 2 teams
return;
}
else
Modified: trunk/data/qcsrc/server/w_grenadelauncher.qc
===================================================================
--- trunk/data/qcsrc/server/w_grenadelauncher.qc 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/qcsrc/server/w_grenadelauncher.qc 2009-04-22 17:52:53 UTC (rev 6568)
@@ -146,8 +146,10 @@
}
.float bot_secondary_grenademooth;
+float w_nexball_weapon(float req);
float w_glauncher(float req)
{
+ if (g_nexball) { return w_nexball_weapon(req); }
if (req == WR_AIM)
{
self.BUTTON_ATCK = FALSE;
Modified: trunk/data/scripts/entities.def
===================================================================
--- trunk/data/scripts/entities.def 2009-04-22 17:52:42 UTC (rev 6567)
+++ trunk/data/scripts/entities.def 2009-04-22 17:52:53 UTC (rev 6568)
@@ -1550,6 +1550,57 @@
targetname: name that identifies this entity so it can be triggered
*/
+/*QUAKED ball_redgoal (1 0 0) ?
+"Red" goal. Defended by blue team, the red team tries to put the ball in there.
+-------- KEYS --------
+noise: sound played when a point is scored
+-------- SPAWNFLAGS --------
+GOAL_TOUCHPLAYER: The trigger also affects ball-carrying players (the ball is then auto-dropped)
+*/
+
+/*QUAKED ball_bluegoal (0 0 1) ?
+"Blue" goal. Defended by red team, the blue team tries to put the ball in there.
+-------- KEYS --------
+noise: sound played when a point is scored
+-------- SPAWNFLAGS --------
+GOAL_TOUCHPLAYER: The trigger also affects ball-carrying players (the ball is then auto-dropped)
+*/
+
+/*QUAKED ball_fault (0.6 0.1 0) ?
+This acts as a goal that always gives points to the opposing team.
+-------- KEYS --------
+noise: sound played when a point is scored
+-------- SPAWNFLAGS --------
+GOAL_TOUCHPLAYER: The trigger also affects ball-carrying players (the ball is then auto-dropped)
+*/
+
+/*QUAKED ball_bound (0.1 0.6 0) ?
+When the ball touches this, it is returned.
+-------- KEYS --------
+noise: sound played when a point is scored
+-------- SPAWNFLAGS --------
+GOAL_TOUCHPLAYER: The trigger also affects ball-carrying players (the ball is then auto-dropped)
+*/
+
+/*QUAKED ball_football (.9 .9 .9) (-16 -16 -16) (16 16 16)
+The soccer type Nexball.
+-------- KEYS --------
+model: set this if you want to use your own model
+scale: if you're using your own model, change this to scale it to 32*32*32
+noise: played when the ball bounces
+noise1: played when the ball is dropped on the map
+*/
+
+/*QUAKED ball_basketball (.5 .2 0) (-16 -16 -16) (16 16 16)
+The basket ball type Nexball.
+-------- KEYS --------
+model: set this if you want to use your own model
+scale: if you're using your own model, change this to scale it to 32*32*32
+noise: played when the ball bounces
+noise1: played when the ball is dropped on the map
+noise2: played when the ball is stolen from the enemy
+*/
+
/*QUAKED item_fuel (.3 .3 1) (-30 -30 0) (30 30 32) FLOATING
Jetpack fuel
-------- KEYS --------
Added: trunk/data/sound/nexball/bounce.ogg
===================================================================
(Binary files differ)
Property changes on: trunk/data/sound/nexball/bounce.ogg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/sound/nexball/drop.ogg
===================================================================
(Binary files differ)
Property changes on: trunk/data/sound/nexball/drop.ogg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/sound/nexball/steal.ogg
===================================================================
(Binary files differ)
Property changes on: trunk/data/sound/nexball/steal.ogg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/textures/nexball/ball.tga
===================================================================
(Binary files differ)
Property changes on: trunk/data/textures/nexball/ball.tga
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/textures/nexball/ball_gloss.tga
===================================================================
(Binary files differ)
Property changes on: trunk/data/textures/nexball/ball_gloss.tga
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/data/textures/nexball/ball_norm.tga
===================================================================
(Binary files differ)
Property changes on: trunk/data/textures/nexball/ball_norm.tga
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/misc/mediasource/graphics/sb-nexball-carrying.svg
===================================================================
--- trunk/misc/mediasource/graphics/sb-nexball-carrying.svg (rev 0)
+++ trunk/misc/mediasource/graphics/sb-nexball-carrying.svg 2009-04-22 17:52:53 UTC (rev 6568)
@@ -0,0 +1,242 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="160"
+ height="160"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="nexball.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/tmp/nexball.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient3174">
+ <stop
+ id="stop3176"
+ offset="0"
+ style="stop-color:#dddddd;stop-opacity:1;" />
+ <stop
+ id="stop3178"
+ offset="1"
+ style="stop-color:#7d7d7d;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3192">
+ <stop
+ style="stop-color:#ffe800;stop-opacity:1;"
+ offset="0"
+ id="stop3194" />
+ <stop
+ style="stop-color:#eb0303;stop-opacity:1;"
+ offset="1"
+ id="stop3196" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3192"
+ id="radialGradient3204"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9636104,-0.3788912,0.1609347,0.8340468,-417.33709,205.85007)"
+ cx="350.32599"
+ cy="477.15244"
+ fx="350.32599"
+ fy="477.15244"
+ r="72.248924" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3174"
+ id="radialGradient3304"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0759078,-0.9724596,1.3927158,1.5408724,-719.39671,95.262834)"
+ cx="380.36703"
+ cy="504.13748"
+ fx="380.36703"
+ fy="504.13748"
+ r="49.857143" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3192"
+ id="radialGradient3309"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.9636104,-0.3788912,0.1609347,0.8340468,-458.56885,233.20173)"
+ cx="350.32599"
+ cy="477.15244"
+ fx="350.32599"
+ fy="477.15244"
+ r="72.248924" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="173.86289"
+ inkscape:cy="95.140549"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1440"
+ inkscape:window-height="825"
+ inkscape:window-x="0"
+ inkscape:window-y="26"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="0,1"
+ position="12.142857,609.28571"
+ id="guide2394" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://www.gnu.org/licenses/gpl-2.0.txt" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Rings"
+ style="display:inline"
+ transform="translate(-253.89393,-446.78742)">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.2;fill:#ffffff;fill-opacity:0.69019607999999999;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path3186"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="matrix(0.742807,0,0,0.742807,34.45497,182.70599)"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.3;fill:#ffffff;fill-opacity:0.69019607999999999;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path3212"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="matrix(0.8001136,0,0,0.8001136,24.50879,156.45428)"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.4;fill:#ffffff;fill-opacity:0.69019607999999999;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path3210"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="matrix(0.8717469,0,0,0.8717469,11.54061,125.69741)"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.5;fill:#ffffff;fill-opacity:0.69019607999999999;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path3208"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="matrix(0.9572736,0,0,0.9572736,-4.50125,90.78161)"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.6;fill:#ffffff;fill-opacity:0.69019607999999999;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path3206"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="translate(-7.43076,76.76486)"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Fire"
+ style="display:inline"
+ transform="translate(-253.89393,-446.78742)">
+ <path
+ style="fill:url(#radialGradient3309);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 400.04641,525.80689 C 400.01034,525.90309 404.5631,486.15158 379.33829,466.96551 C 354.96964,448.43064 352.31671,449.28784 352.31671,449.28784 C 352.31671,449.28784 376.05529,482.1178 365.19615,493.73455 C 354.33701,505.35131 350.80148,498.78531 350.80148,498.78531 L 312.41568,453.83352 C 312.41568,453.83352 343.47788,507.87669 323.7799,515.95791 C 304.08193,524.03913 263.17075,483.12795 263.17075,483.12795 C 263.17075,483.12795 280.34334,505.60384 282.36364,508.38176 C 284.38395,511.15968 314.94107,549.79801 287.66695,542.22187 C 260.39283,534.64572 255.84714,535.1508 255.84714,535.1508 C 255.84714,535.1508 310.39538,564.19269 317.71899,573.78914 C 325.04259,583.38559 401.05656,525.30182 400.04641,525.80689 z"
+ id="path3190"
+ sodipodi:nodetypes="cscsccscsscsc"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ d="M 400.75444,526.06094 C 400.71837,526.15714 405.27113,486.40563 380.04632,467.21956 C 355.67767,448.68469 353.02474,449.54189 353.02474,449.54189 C 353.02474,449.54189 376.76332,482.37185 365.90418,493.9886 C 355.04504,505.60536 351.50951,499.03936 351.50951,499.03936 L 313.12371,454.08757 C 313.12371,454.08757 344.18591,508.13074 324.48793,516.21196 C 304.78996,524.29318 263.87878,483.382 263.87878,483.382 C 263.87878,483.382 281.05137,505.85789 283.07167,508.63581 C 285.09198,511.41373 315.6491,550.05206 288.37498,542.47592 C 261.10086,534.89977 256.55517,535.40485 256.55517,535.40485 C 256.55517,535.40485 311.10341,564.44674 318.42702,574.04319 C 325.75062,583.63964 401.76459,525.55587 400.75444,526.06094 z"
+ id="path3214"
+ sodipodi:nodetypes="cscsccscsscsc"
+ inkscape:export-filename="/tmp/path2389.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+ <g
+ inkscape:label="Ball"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline"
+ transform="translate(-253.89393,-446.78742)">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient3304);fill-opacity:1;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+ id="path2389"
+ sodipodi:cx="363.57144"
+ sodipodi:cy="473.07648"
+ sodipodi:rx="47.857143"
+ sodipodi:ry="47.857143"
+ d="M 411.42859,473.07648 A 47.857143,47.857143 0 1 1 315.7143,473.07648 A 47.857143,47.857143 0 1 1 411.42859,473.07648 z"
+ transform="translate(-1.1958991,82.105473)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ </g>
+</svg>
More information about the nexuiz-commits
mailing list