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