]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator/mutator_physical_items.qc
Allow single letter uldr, also make sure it isn't case sensitive
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator / mutator_physical_items.qc
1 #ifdef IMPLEMENTATION
2 REGISTER_MUTATOR(physical_items, cvar("g_physical_items"))
3 {
4         // check if we have a physics engine
5         MUTATOR_ONADD
6         {
7                 if (!(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")))
8                 {
9                         LOG_TRACE("Warning: Physical items are enabled but no physics engine can be used. Reverting to old items.\n");
10                         return -1;
11                 }
12         }
13
14         MUTATOR_ONROLLBACK_OR_REMOVE
15         {
16                 // nothing to roll back
17         }
18
19         MUTATOR_ONREMOVE
20         {
21                 LOG_INFO("This cannot be removed at runtime\n");
22                 return -1;
23         }
24
25         return 0;
26 }
27
28 .vector spawn_origin, spawn_angles;
29
30 void physical_item_think()
31 {SELFPARAM();
32         self.nextthink = time;
33
34         self.alpha = self.owner.alpha; // apply fading and ghosting
35
36         if(!self.cnt) // map item, not dropped
37         {
38                 // copy ghost item properties
39                 self.colormap = self.owner.colormap;
40                 self.colormod = self.owner.colormod;
41                 self.glowmod = self.owner.glowmod;
42
43                 // if the item is not spawned, make sure the invisible / ghost item returns to its origin and stays there
44                 if(autocvar_g_physical_items_reset)
45                 {
46                         if(self.owner.wait > time) // awaiting respawn
47                         {
48                                 setorigin(self, self.spawn_origin);
49                                 self.angles = self.spawn_angles;
50                                 self.solid = SOLID_NOT;
51                                 self.alpha = -1;
52                                 self.movetype = MOVETYPE_NONE;
53                         }
54                         else
55                         {
56                                 self.alpha = 1;
57                                 self.solid = SOLID_CORPSE;
58                                 self.movetype = MOVETYPE_PHYSICS;
59                         }
60                 }
61         }
62
63         if(!self.owner.modelindex)
64                 remove(self); // the real item is gone, remove this
65 }
66
67 void physical_item_touch()
68 {SELFPARAM();
69         if(!self.cnt) // not for dropped items
70         if (ITEM_TOUCH_NEEDKILL())
71         {
72                 setorigin(self, self.spawn_origin);
73                 self.angles = self.spawn_angles;
74         }
75 }
76
77 void physical_item_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
78 {SELFPARAM();
79         if(!self.cnt) // not for dropped items
80         if(ITEM_DAMAGE_NEEDKILL(deathtype))
81         {
82                 setorigin(self, self.spawn_origin);
83                 self.angles = self.spawn_angles;
84         }
85 }
86
87 MUTATOR_HOOKFUNCTION(physical_items, Item_Spawn)
88 {SELFPARAM();
89         if(self.owner == world && autocvar_g_physical_items <= 1)
90                 return false;
91         if (self.spawnflags & 1) // floating item
92                 return false;
93
94         // The actual item can't be physical and trigger at the same time, so make it invisible and use a second entity for physics.
95         // Ugly hack, but unless SOLID_TRIGGER is gotten to work with MOVETYPE_PHYSICS in the engine it can't be fixed.
96         entity wep;
97         wep = spawn();
98         _setmodel(wep, self.model);
99         setsize(wep, self.mins, self.maxs);
100         setorigin(wep, self.origin);
101         wep.angles = self.angles;
102         wep.velocity = self.velocity;
103
104         wep.owner = self;
105         wep.solid = SOLID_CORPSE;
106         wep.movetype = MOVETYPE_PHYSICS;
107         wep.takedamage = DAMAGE_AIM;
108         wep.effects |= EF_NOMODELFLAGS; // disable the spinning
109         wep.colormap = self.owner.colormap;
110         wep.glowmod = self.owner.glowmod;
111         wep.damageforcescale = autocvar_g_physical_items_damageforcescale;
112         wep.dphitcontentsmask = self.dphitcontentsmask;
113         wep.cnt = (self.owner != world);
114
115         wep.think = physical_item_think;
116         wep.nextthink = time;
117         wep.touch = physical_item_touch;
118         wep.event_damage = physical_item_damage;
119
120         if(!wep.cnt)
121         {
122                 // fix the spawn origin
123                 setorigin(wep, wep.origin + '0 0 1');
124                 entity oldself;
125                 oldself = self;
126                 WITH(entity, self, wep, builtin_droptofloor());
127         }
128
129         wep.spawn_origin = wep.origin;
130         wep.spawn_angles = self.angles;
131
132         self.effects |= EF_NODRAW; // hide the original weapon
133         self.movetype = MOVETYPE_FOLLOW;
134         self.aiment = wep; // attach the original weapon
135         self.SendEntity = func_null;
136
137         return false;
138 }
139 #endif