-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathexplosive.py
214 lines (160 loc) · 5.83 KB
/
explosive.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
from collections import deque
from pyspades.common import Vertex3
from piqueserver.commands import command, player_only
from milsim.common import (
alive_only, apply_item, has_item,
take_item, take_items, format_taken_items
)
from milsim.blast import sendGrenadePacket, explode
from milsim.types import TileEntity, Item
class Explosive(TileEntity):
r1, r2 = 7.0, 30.0
Δx, Δy, Δz = 0, 0, 0
x0, y0, z0 = 0.5, 0.5, 0.5
def __init__(self, protocol, position, player_id):
TileEntity.__init__(self, protocol, position)
self.player_id = player_id
def explode(self):
self.protocol.remove_tile_entity(*self.position)
if player := self.protocol.take_player(self.player_id):
x, y, z = self.position
player.grenade_destroy(x + self.Δx, y + self.Δy, z + self.Δz)
loc = Vertex3(x + self.x0, y + self.y0, z + self.z0)
explode(self.r1, self.r2, player, loc)
sendGrenadePacket(self.protocol, player.player_id, loc, Vertex3(0, 0, 0), 0)
class Landmine(Explosive):
Δz = -1
z0 = -0.5
on_pressure = Explosive.explode
on_explosion = Explosive.explode
on_destroy = Explosive.explode
class Charge(Explosive):
r1, r2 = 20.0, 60.0
on_explosion = Explosive.explode
on_destroy = Explosive.explode
class ExplosiveItem(Item):
tile_entity_class = NotImplemented
def apply(self, player):
if loc := player.world_object.cast_ray(7):
x, y, z = loc
if 63 <= z: return "{} cannot be placed on water".format(self.name)
return self.spawn(player, x, y, z)
else:
return "{} cannot be placed that far away from you".format(self.name)
def spawn(self, player, x, y, z):
player.inventory.remove(self)
protocol = player.protocol
protocol.add_tile_entity(
self.tile_entity_class, protocol, (x, y, z), player.player_id
)
return "{} placed at ({}, {}, {})".format(self.name, x, y, z)
class LandmineItem(ExplosiveItem):
tile_entity_class = Landmine
name = "Landmine"
mass = 0.550
def spawn(self, player, x, y, z):
if e := player.protocol.get_tile_entity(x, y, z):
if isinstance(e, Landmine):
player.inventory.remove(self)
e.explode()
return
else:
return "{} cannot be placed here".format(self.name)
return ExplosiveItem.spawn(self, player, x, y, z)
class DetonatorItem(Item):
mass = 0.150
limit = 4
def __init__(self):
Item.__init__(self)
self.targets = []
@property
def name(self):
return "Detonator ({})".format(len(self.targets))
def add(self, x, y, z):
self.targets.append((x, y, z))
def available(self):
return len(self.targets) < self.limit
def apply(self, player):
protocol = player.protocol
for x, y, z in self.targets:
if e := protocol.get_tile_entity(x, y, z):
if isinstance(e, Charge):
e.explode()
self.targets = []
class ChargeItem(ExplosiveItem):
tile_entity_class = Charge
name = "Charge"
mass = 0.700
def spawn(self, player, x, y, z):
if player.protocol.get_tile_entity(x, y, z) is not None:
return "{} cannot be placed here".format(self.name)
it = filter(
lambda o: isinstance(o, DetonatorItem) and o.available(),
player.inventory
)
if o := next(it, None):
o.add(x, y, z)
return ExplosiveItem.spawn(self, player, x, y, z)
else:
return "You don't have an available detonator"
@command('mine', 'm')
@alive_only
def use_landmine(player):
"""
Put a mine on the given block
/m or /mine
"""
return apply_item(LandmineItem, player, errmsg = "You do not have mines")
@command('charge', 'c')
@alive_only
def use_charge(player):
"""
Put a charge on the given block
/c or /charge
"""
return apply_item(ChargeItem, player, errmsg = "You do not have charges")
@command('detonate', 'de')
@alive_only
def use_detonator(player):
"""
Activate a detonator
/de or /detonate
"""
return apply_item(DetonatorItem, player, errmsg = "You do not have a detonator")
def take_detonator(player, n):
if not has_item(player, DetonatorItem):
yield from take_item(player, DetonatorItem)
yield from take_items(player, ChargeItem, n, 3)
@command('takecharge', 'tc')
@alive_only
def take_charge(player, argval = 1):
"""
Try to take a given number of charges and a detonator
/tc [n] or /takecharge
"""
n = int(argval)
if n <= 0: return "Invalid number of charges"
return format_taken_items(take_detonator(player, n))
def apply_script(protocol, connection, config):
def explosive_default_tent_loadout(self):
yield from protocol.default_tent_loadout(self)
for k in range(100):
yield LandmineItem()
yield DetonatorItem()
yield ChargeItem()
yield ChargeItem()
def explosive_default_loadout(self):
yield from connection.default_loadout(self)
for k in range(2):
yield LandmineItem()
class MineGrenadeTool(protocol.GrenadeTool):
def on_rmb_press(self):
protocol.GrenadeTool.on_rmb_press(self)
if reply := apply_item(ExplosiveItem, self.player, errmsg = "You do not have explosives"):
self.player.send_chat(reply)
class ExplosiveProtocol(protocol):
default_tent_loadout = explosive_default_tent_loadout
GrenadeTool = MineGrenadeTool
class ExplosiveConnection(connection):
default_loadout = explosive_default_loadout
return ExplosiveProtocol, ExplosiveConnection