Xonotic
teleport.qc
Go to the documentation of this file.
1 #include "teleport.qh"
2 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_TELEPORT)
3 
4 #ifdef SVQC
5 void trigger_teleport_use(entity this, entity actor, entity trigger)
6 {
7  if(teamplay)
8  this.team = actor.team;
9 #ifdef SVQC
10  this.SendFlags |= SF_TRIGGER_UPDATE;
11 #endif
12 }
13 #endif
14 
15 bool Teleport_Active(entity this, entity player)
16 {
17  if (this.active != ACTIVE_ACTIVE)
18  return false;
19 
20 #ifdef SVQC
21  if (!player.teleportable)
22  return false;
23 
24  if(player.vehicle)
25  if(!player.vehicle.teleportable)
26  return false;
27 
28  if(IS_TURRET(player))
29  return false;
30 #elif defined(CSQC)
31  if(!IS_PLAYER(player))
32  return false;
33 #endif
34 
35  if(IS_DEAD(player))
36  return false;
37 
38  if(this.team)
39  if(((this.spawnflags & INVERT_TEAMS) == 0) == (DIFF_TEAM(this, player)))
40  return false;
41 
42  return true;
43 }
44 
45 void Teleport_Touch(entity this, entity toucher)
46 {
47  entity player = toucher;
48 
49  if(!Teleport_Active(this, player))
50  return;
51 
52  EXACTTRIGGER_TOUCH(this, player);
53 
54 #ifdef SVQC
55  if(IS_PLAYER(player))
56  RemoveGrapplingHooks(player);
57 #endif
58 
59  entity e;
60  e = Simple_TeleportPlayer(this, player);
61 
62 #ifdef SVQC
63  string s = this.target; this.target = string_null;
64  SUB_UseTargets(this, player, player); // TODO: should we be using toucher for trigger too?
65  if (!this.target) this.target = s;
66 
67  SUB_UseTargets(e, player, player);
68 #endif
69 }
70 
71 #ifdef SVQC
72 void target_teleport_use(entity this, entity actor, entity trigger)
73 {
74  entity player = actor;
75 
76  if(!Teleport_Active(this, player))
77  return;
78 
79  if(IS_PLAYER(player))
80  RemoveGrapplingHooks(player);
81 
82  entity e = Simple_TeleportPlayer(this, player);
83 
84  string s = this.target; this.target = string_null;
85  SUB_UseTargets(this, player, player); // TODO: should we be using toucher for trigger too?
86  if (!this.target)
87  {
88  this.target = s;
89  }
90 
91  if(e != this) // only activate the target teleporter if target is different
92  SUB_UseTargets(e, player, player);
93 }
94 #endif
95 
96 #ifdef SVQC
97 float trigger_teleport_send(entity this, entity to, float sf)
98 {
99  WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_TELEPORT);
100 
101  WriteByte(MSG_ENTITY, this.team);
102  WriteInt24_t(MSG_ENTITY, this.spawnflags);
103  WriteByte(MSG_ENTITY, this.active);
104  WriteCoord(MSG_ENTITY, this.speed);
105 
106  trigger_common_write(this, true);
107 
108  return true;
109 }
110 
111 void trigger_teleport_link(entity this)
112 {
113  //trigger_link(this, trigger_teleport_send);
114 }
115 
116 spawnfunc(trigger_teleport)
117 {
118  this.angles = '0 0 0';
119 
120  this.active = ACTIVE_ACTIVE;
121  //trigger_init(this); // only for predicted triggers?
123  this.use = trigger_teleport_use;
124 
125  if(this.noise != "")
126  FOREACH_WORD(this.noise, true, precache_sound(it));
127 
128  // this must be called to spawn the teleport waypoints for bots
129  InitializeEntity(this, teleport_findtarget, INITPRIO_FINDTARGET);
130 
131  if (!this.target || this.target == "")
132  {
133  objerror (this, "Teleporter with no target");
134  return;
135  }
136 
137  IL_PUSH(g_teleporters, this);
138 }
139 
140 void target_teleporter_checktarget(entity this)
141 {
142  // target_teleporter is used in many strange ways
143  // we must attempt to figure out which way it is being used for in this instance
144 
145  if(!this.target || this.target == "")
146  {
147  // this target_teleporter has no target
148  // so it must be either a destination for a teleporter or a teleporter itself
149  bool is_teleporter_target = false;
150  // NOTE: target2, target3, target4 unsupported, this may not be necessary as DeFrag maps have no such targets
152  {
153  if(it.classname == "trigger_teleport" || it.classname == "target_teleporter")
154  {
155  is_teleporter_target = true;
156  break; // no need to keep looping once a valid target is found
157  }
158  });
159 
160  if(is_teleporter_target)
161  {
162  // there were teleporters found targeting this, so it must be a destination!
163  spawnfunc_info_teleport_destination(this);
164  return;
165  }
166 
167  // set this entity up to be a teleporter, since it can be activated as one
168  this.enemy = this;
169  this.mangle = this.angles;
170  this.angles = '0 0 0';
171  }
172 
173  // seeing as this entity isn't targeted by a teleporter, it must be a teleporter itself
174 
175  this.active = ACTIVE_ACTIVE;
176  this.use = target_teleport_use;
177 
178  if(this.noise && this.noise != "")
179  FOREACH_WORD(this.noise, true, precache_sound(it));
180 
181  if(this.target && this.target != "") // no need to find a target on this entity, as it does not have one and .enemy is already set as required
182  teleport_findtarget(this);
183 }
184 
185 spawnfunc(target_teleporter)
186 {
187  InitializeEntity(this, target_teleporter_checktarget, INITPRIO_FINDTARGET);
188 }
189 #elif defined(CSQC)
190 NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
191 {
192  this.classname = "trigger_teleport";
193  if(isnew)
194  IL_PUSH(g_teleporters, this);
195  int mytm = ReadByte();
196  if(mytm)
197  {
198  this.team = mytm - 1;
199  }
200  this.spawnflags = ReadInt24_t();
201  this.active = ReadByte();
202  this.speed = ReadCoord();
203 
204  trigger_common_read(this, true);
205 
206  this.entremove = trigger_remove_generic;
207  this.solid = SOLID_TRIGGER;
208  //settouch(this, trigger_push_touch);
209  this.move_time = time;
210  defer(this, 0.25, teleport_findtarget);
211 
212  return true;
213 }
214 
215 #endif
string string_null
Definition: nil.qh:9
#define REGISTER_NET_LINKED(id)
Definition: net.qh:67
float speed
Definition: subs.qh:41
const int INVERT_TEAMS
Definition: defs.qh:10
#define EXACTTRIGGER_INIT
Definition: common.qh:117
string noise
Definition: progsdefs.qc:209
void teleport_findtarget(entity this)
Definition: teleporters.qc:237
int team
Definition: main.qh:157
#define EXACTTRIGGER_TOUCH(e, t)
Definition: common.qh:116
IntrusiveList g_teleporters
Definition: teleporters.qh:10
entity() spawn
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition: triggers.qc:366
#define NET_HANDLE(id, param)
Definition: net.qh:12
void Teleport_Touch(entity this, entity toucher)
Definition: teleport.qc:45
entity to
Definition: self.qh:96
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
string classname
Definition: csprogsdefs.qc:107
#define DIFF_TEAM(a, b)
Definition: teams.qh:240
float spawnflags
Definition: progsdefs.qc:191
#define IS_TURRET(v)
Definition: utils.qh:23
#define FOREACH_WORD(words, cond, body)
Definition: iter.qh:33
#define FOREACH_ENTITY_STRING(fld, match, body)
Definition: iter.qh:184
entity Simple_TeleportPlayer(entity teleporter, entity player)
Definition: teleporters.qc:180
entity enemy
Definition: sv_ctf.qh:143
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
const int ACTIVE_ACTIVE
Definition: defs.qh:37
float teamplay
Definition: progsdefs.qc:31
#define IS_DEAD(s)
Definition: utils.qh:26
void RemoveGrapplingHooks(entity pl)
Definition: hook.qc:78
void InitializeEntity(entity e, void(entity this) func, int order)
Definition: world.qc:2146
float move_time
Definition: movetypes.qh:77
bool Teleport_Active(entity this, entity player)
Definition: teleport.qc:15
const float SOLID_TRIGGER
Definition: csprogsdefs.qc:245
string targetname
Definition: progsdefs.qc:194
int active
Definition: defs.qh:34
vector mangle
Definition: subs.qh:51
vector angles
Definition: csprogsdefs.qc:104
#define use
Definition: csprogsdefs.qh:50
string target
Definition: progsdefs.qc:193
float time
Definition: csprogsdefs.qc:16
#define IS_PLAYER(v)
Definition: utils.qh:9
float solid
Definition: csprogsdefs.qc:99
const int SF_TRIGGER_UPDATE
Definition: defs.qh:23