r4277 - trunk/data/qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Tue Sep 2 03:29:53 EDT 2008
Author: div0
Date: 2008-09-02 03:29:52 -0400 (Tue, 02 Sep 2008)
New Revision: 4277
Added:
trunk/data/qcsrc/server/portals.qh
Modified:
trunk/data/qcsrc/server/portals.qc
trunk/data/qcsrc/server/progs.src
trunk/data/qcsrc/server/t_teleporters.qc
trunk/data/qcsrc/server/w_grenadelauncher.qc
Log:
mall stupid mod: the Portar (compile with -DPORTAR for testing)
Modified: trunk/data/qcsrc/server/portals.qc
===================================================================
--- trunk/data/qcsrc/server/portals.qc 2008-09-01 19:18:44 UTC (rev 4276)
+++ trunk/data/qcsrc/server/portals.qc 2008-09-02 07:29:52 UTC (rev 4277)
@@ -1,3 +1,11 @@
+.vector portal_transform;
+.vector portal_safe_origin;
+.float portal_wants_to_vanish;
+.float portal_id;
+.float portal_activatetime;
+
+.entity portal_in, portal_out;
+
vector fixedvectoangles(vector v)
{
vector a;
@@ -6,34 +14,66 @@
return a;
}
+vector fixedvectoangles2(vector v, vector w)
+{
+ vector a;
+ a = vectoangles(v, w);
+ a_x = -a_x;
+ return a;
+}
+
vector Portal_Transform_Apply(vector transform, vector v)
{
makevectors(transform);
return v_forward * v_x
- + v_right * v_y
+ + v_right * (-v_y)
+ v_up * v_z;
}
+vector Portal_Transform_Multiply(vector t1, vector t2)
+{
+ vector m_forward, m_up;
+ makevectors(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 fixedvectoangles2(m_forward, m_up);
+}
+
vector Portal_Transform_Invert(vector transform)
{
+ vector i_forward, i_up;
makevectors(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?
- return fixedvectoangles(
- '1 0 0' * v_forward_x + '0 1 0' * v_right_x + '0 0 1' * v_up_x,
- '1 0 0' * v_forward_y + '0 1 0' * v_right_y + '0 0 1' * v_up_y
- );
+ 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 = fixedvectoangles2(i_forward, i_up);
+ print("Transform: ", vtos(transform), "\n");
+ print("Inverted: ", vtos(v), "\n");
+ print("Verify: ", vtos(Portal_Transform_Multiply(v, transform)), "\n");
+ makevectors(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 fixedvectoangles2(i_forward, i_up);
}
-vector Portal_Transform_Multiply(vector t1, vector t2)
+vector Portal_Transform_TurnDirection(vector transform)
{
- vector vx, vy;
- makevectors(t2); vx = v_forward; vy = v_right;
- vx = Portal_Transform_Apply(t1, vx);
- vy = Portal_Transform_Apply(t1, vy);
- return fixedvectoangles(vx, vy);
+ vector t_angles;
+ t_angles_x = -transform_x;
+ t_angles_y = mod(transform_y + 180, 360);
+ t_angles_z = -transform_z;
+ return t_angles;
}
vector Portal_Transform_Divide(vector to_transform, vector from_transform)
@@ -43,28 +83,152 @@
void Portal_TeleportPlayer(entity teleporter, entity player)
{
- vector to, transform;
- to = teleporter.velocity;
- transform = teleporter.mangle;
- TeleportPlayer(teleporter, player, to, Portal_Transform_Multiply(transform, player.angles), Portal_Transform_Apply(transform, player.velocity));
+ vector from, to, safe, step, transform, ang;
+ from = teleporter.origin;
+ to = teleporter.enemy.origin;
+ transform = teleporter.portal_transform;
+
+ to = to + Portal_Transform_Apply(teleporter.portal_transform, player.origin - from);
+ // this now is INSIDE the plane... can't use that
+
+ // shift it out
+ makevectors(teleporter.enemy.angles);
+ 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)
+ error("'safe' teleport location is not safe!");
+ safe = trace_endpos;
+ tracebox(safe, PL_MIN, PL_MAX, to, MOVE_NOMONSTERS, player);
+ if(trace_startsolid)
+ error("trace_endpos in solid!");
+ to = trace_endpos;
+
+ if(player.classname == "player")
+ {
+ ang = Portal_Transform_Multiply(transform, player.v_angle);
+ ang_z = player.angles_z;
+ }
+ else
+ {
+ ang = Portal_Transform_Multiply(transform, player.angles);
+ }
+
+ print("previous velocity: ", vtos(player.velocity), "\n");
+ print("previous origin: ", vtos(player.origin), "\n");
+ TeleportPlayer(teleporter, player, to, ang, Portal_Transform_Apply(transform, player.velocity));
+ print("new velocity: ", vtos(player.velocity), "\n");
+ print("new origin: ", vtos(player.origin), "\n");
}
-float Portal_Fix(entity teleporter)
+float Portal_FindSafeOrigin(entity portal)
{
- teleporter.mins = PL_MIN - '2 2 2';
- teleporter.maxs = PL_MAX + '2 2 2';
- return move_out_of_solid(teleporter);
+ vector o;
+ o = portal.origin;
+ portal.mins = PL_MIN - '8 8 8';
+ portal.maxs = PL_MAX + '8 8 8';
+ if(!move_out_of_solid(portal))
+ {
+ print("NO SAFE ORIGIN\n");
+ return 0;
+ }
+ portal.portal_safe_origin = portal.origin;
+ setorigin(portal, o);
+ return 1;
}
+void Portal_Touch()
+{
+ if(time < self.portal_activatetime)
+ return;
+ makevectors(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;
+ }
+ Portal_TeleportPlayer(self, other);
+
+ // reset fade counter
+ self.portal_wants_to_vanish = 0;
+ self.nextthink = time + 60;
+}
+
+void Portal_MakeBrokenPortal(entity portal)
+{
+ portal.solid = SOLID_NOT;
+ portal.touch = SUB_Null;
+ portal.effects = 0;
+ portal.colormod = '1 1 1';
+}
+
+void Portal_MakeInPortal(entity portal)
+{
+ portal.solid = SOLID_TRIGGER;
+ portal.touch = Portal_Touch;
+ portal.effects = EF_RED;
+ portal.colormod = '1 0 0';
+}
+
+void Portal_MakeOutPortal(entity portal)
+{
+ portal.solid = SOLID_NOT;
+ portal.touch = SUB_Null;
+ portal.effects = EF_STARDUST;
+ portal.colormod = '0 0 1';
+}
+
+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.mangle = Portal_Transform_Divide(-(destination.angles), teleporter.angles);
- teleporter.touch = Portal_Touch;
- teleporter.cnt = 0;
- destination.touch = SUB_Null;
- destination.cnt = 1;
+ teleporter.portal_transform = Portal_Transform_Divide(Portal_Transform_TurnDirection(destination.angles), teleporter.angles);
+ teleporter.enemy = destination;
+ destination.enemy = teleporter;
+ Portal_MakeInPortal(teleporter);
+ Portal_MakeOutPortal(destination);
+ teleporter.nextthink = time + 60;
+ destination.nextthink = time + 60;
+ teleporter.portal_wants_to_vanish = 0;
+ destination.portal_wants_to_vanish = 0;
}
+void Portal_Vanish()
+{
+ self.portal_wants_to_vanish = 1;
+
+ if(self.enemy)
+ if(!self.enemy.portal_wants_to_vanish)
+ return;
+
+ SUB_SetFade(self, time + 1, 1);
+ if(self.enemy)
+ {
+ SUB_SetFade(self.enemy, time + 1, 1);
+ Portal_Disconnect(self, self.enemy);
+ }
+}
+
+void Portal_RequestVanish(entity portal)
+{
+ entity oldself;
+ oldself = self;
+ self = portal;
+ if(self.enemy)
+ self.enemy.portal_wants_to_vanish = 1;
+ Portal_Vanish();
+ self = oldself;
+}
+
entity Portal_Spawn(entity own, vector org, vector ang)
{
entity portal;
@@ -73,5 +237,79 @@
portal.owner = own;
portal.origin = org;
portal.angles = ang;
- setmodel(portal, ...);
+ portal.think = Portal_Vanish;
+ portal.nextthink = time + 60;
+ portal.portal_activatetime = time + 0.1;
+ setmodel(portal, "models/items/g_h100.md3");
+
+ if(!Portal_FindSafeOrigin(portal))
+ {
+ remove(portal);
+ return world;
+ }
+
+ setsize(portal, '-32 -32 -32', '32 32 32');
+
+ return portal;
}
+
+float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id_val)
+{
+ if(own.portal_in)
+ {
+ if(own.portal_out)
+ {
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_RequestVanish(own.portal_out);
+ }
+ own.portal_out = own.portal_in;
+ own.portal_in = world;
+ own.portal_out.portal_id = portal_id_val;
+ }
+ else if(own.portal_out)
+ {
+ print("this DID happen, no idea why (1)\n");
+ Portal_RequestVanish(own.portal_out);
+ own.portal_out = world;
+ }
+
+ print("Plane normal: ", vtos(trace_plane_normal), "\n");
+ print("Portal angles: ", vtos(fixedvectoangles(trace_plane_normal)), "\n");
+ own.portal_in = Portal_Spawn(own, trace_endpos + trace_plane_normal, fixedvectoangles2(trace_plane_normal, dir));
+ if(!own.portal_in)
+ return 0;
+ own.portal_in.portal_id = portal_id_val;
+
+ if(own.portal_out)
+ Portal_Connect(own.portal_in, own.portal_out);
+
+ return 1;
+}
+
+float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id_val)
+{
+ if(!own.portal_in)
+ return 0; // sorry
+
+ if(own.portal_in.portal_id != portal_id_val)
+ return 0; // we need MATCHING portals
+
+ if(own.portal_out)
+ {
+ Portal_Disconnect(own.portal_in, own.portal_out);
+ Portal_RequestVanish(own.portal_out);
+ own.portal_out = world;
+ }
+
+ print("Plane normal: ", vtos(trace_plane_normal), "\n");
+ print("Portal angles: ", vtos(fixedvectoangles(trace_plane_normal)), "\n");
+ own.portal_out = Portal_Spawn(own, trace_endpos + trace_plane_normal, fixedvectoangles2(trace_plane_normal, dir));
+ if(!own.portal_out)
+ return 0;
+ own.portal_out.portal_id = portal_id_val;
+
+ Portal_Connect(own.portal_in, own.portal_out);
+ print("Portal transform: ", vtos(own.portal_in.portal_transform), "\n");
+
+ return 1;
+}
Added: trunk/data/qcsrc/server/portals.qh
===================================================================
--- trunk/data/qcsrc/server/portals.qh (rev 0)
+++ trunk/data/qcsrc/server/portals.qh 2008-09-02 07:29:52 UTC (rev 4277)
@@ -0,0 +1,2 @@
+float Portal_SpawnOutPortalAtTrace(entity own, vector dir, float portal_id);
+float Portal_SpawnInPortalAtTrace(entity own, vector dir, float portal_id);
Modified: trunk/data/qcsrc/server/progs.src
===================================================================
--- trunk/data/qcsrc/server/progs.src 2008-09-01 19:18:44 UTC (rev 4276)
+++ trunk/data/qcsrc/server/progs.src 2008-09-02 07:29:52 UTC (rev 4277)
@@ -18,6 +18,8 @@
../common/mapinfo.qh
+portals.qh
+
scores.qh
ipban.qh
@@ -131,3 +133,5 @@
tturrets/include/turret_tturrets.qh
scores.qc
+
+portals.qc
Modified: trunk/data/qcsrc/server/t_teleporters.qc
===================================================================
--- trunk/data/qcsrc/server/t_teleporters.qc 2008-09-01 19:18:44 UTC (rev 4276)
+++ trunk/data/qcsrc/server/t_teleporters.qc 2008-09-02 07:29:52 UTC (rev 4277)
@@ -16,60 +16,64 @@
player.angles = to_angles;
player.fixangle = TRUE;
player.velocity = to_velocity;
- RemoveGrapplingHook(player);
- // Kill anyone else in the teleporter box (NO MORE TDEATH)
- if(player.takedamage && !g_race)
+ if(player.classname == "player")
{
- vector deathmin;
- vector deathmax;
- float deathradius;
- deathmin = player.absmin;
- deathmax = player.absmax;
- 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, player, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
- else if (player.health < 1) // corpses gib
- Damage (head, teleporter, player, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
- else // dead bodies and monsters gib themselves instead of telefragging
- Damage (player, teleporter, player, 10000, DEATH_TELEFRAG, player.origin, '0 0 0');
- }
- }
+ RemoveGrapplingHook(player);
- // 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(player.takedamage && !g_race)
+ {
+ vector deathmin;
+ vector deathmax;
+ float deathradius;
+ deathmin = player.absmin;
+ deathmax = player.absmax;
+ 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, player, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+ else if (player.health < 1) // corpses gib
+ Damage (head, teleporter, player, 10000, DEATH_TELEFRAG, head.origin, '0 0 0');
+ else // dead bodies and monsters gib themselves instead of telefragging
+ Damage (player, teleporter, player, 10000, DEATH_TELEFRAG, player.origin, '0 0 0');
+ }
+ }
- // player no longer is on ground
- player.flags = player.flags - (player.flags & FL_ONGROUND);
+ // 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");
- // reset tracking of oldvelocity for impact damage (sudden velocity changes)
- player.oldvelocity = player.velocity;
+ // player no longer is on ground
+ player.flags = player.flags - (player.flags & FL_ONGROUND);
- // 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;
- }
+ // reset tracking of oldvelocity for impact damage (sudden velocity changes)
+ player.oldvelocity = player.velocity;
- // stop player name display
- {
- oldself = self;
- self = player;
- ClearSelectedPlayer();
- self = oldself;
+ // 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 = player;
+ ClearSelectedPlayer();
+ self = oldself;
+ }
}
}
Modified: trunk/data/qcsrc/server/w_grenadelauncher.qc
===================================================================
--- trunk/data/qcsrc/server/w_grenadelauncher.qc 2008-09-01 19:18:44 UTC (rev 4276)
+++ trunk/data/qcsrc/server/w_grenadelauncher.qc 2008-09-02 07:29:52 UTC (rev 4277)
@@ -1,4 +1,8 @@
+#ifdef PORTAR
+.float portar_grenade_id;
+#endif
+#ifndef PORTAR
void W_Grenade_Explode (void)
{
vector org2;
@@ -72,6 +76,27 @@
self.think ();
}
}
+#else
+void W_Grenade_Explode (void)
+{
+ remove(self);
+}
+void W_Grenade_Touch1 (void)
+{
+ print(vtos(trace_plane_normal), "\n");
+ if(self.portar_grenade_id == 0)
+ {
+ self.portar_grenade_id = time;
+ if(!Portal_SpawnInPortalAtTrace(self.owner, self.velocity, self.portar_grenade_id))
+ remove(self);
+ }
+ else
+ {
+ Portal_SpawnOutPortalAtTrace(self.owner, self.velocity, self.portar_grenade_id);
+ remove(self);
+ }
+}
+#endif
void W_Grenade_Attack (void)
{
@@ -110,6 +135,7 @@
void W_Grenade_Attack2 (void)
{
+#ifndef PORTAR
local entity gren;
if (cvar("g_use_ammunition"))
@@ -145,6 +171,9 @@
gren.angles = vectoangles (gren.velocity);
gren.flags = FL_PROJECTILE;
+#else
+ // nothing yet (maybe find the last one and detonate it?)
+#endif
}
.float bot_secondary_grenademooth;
More information about the nexuiz-commits
mailing list