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
dofile("sys/lua/wrapper.lua")
CREATURE = {
ALIVE = {},
LIST = {
{
NAME = "Zombie",
HITPOINT = 100,
MOVESPEED = 6,
VISION = 400,
IMAGE = "gfx/npc/vortigaunt.bmp",
SOUND = {},
HIT_MODE = 103,
HIT_ZONE = 22,
ATTACK = { DAMAGE = 0, RANGE = 32, SPEED = 0, TYPE = 0 },
SPAWN = { RATE = 100, TILE = {}, LIMIT = 5, POSITION = {{0, 0}, {100, 100}} }
}
}
}
hook("startround", function() CREATURE.ALIVE = {} end)
hook("ms100", function()
if #CREATURE.ALIVE < 5 then
local creature, tile_x, tile_y = deepcopy(CREATURE.LIST[1])
repeat tile_x, tile_y = math.random(creature.SPAWN.POSITION[1][1], creature.SPAWN.POSITION[2][1]), math.random(creature.SPAWN.POSITION[1][2], creature.SPAWN.POSITION[2][2])
until tile(tile_x, tile_y, "walkable")
creature.POSITION_X, creature.POSITION_Y = math.floor(tile_x * 32 + 16), math.floor(tile_y * 32 + 16)
CREATURE:insert(creature)
end
for _, creature in pairs(CREATURE.ALIVE) do creature:update() end
end)
hook("hitzone", function(z, x, c, v, b, n, m)
for _, creature in pairs(CREATURE.ALIVE) do
msg("aaa")
if z == creature.IMAGE then
creature.HITPOINT = creature.HITPOINT - m
if creature.HITPOINT <= 0 then creature:remove() end
end
return true
end
end)
hook("hit", function(player_id, source, weapon_id, hit_damage)
if type(source) == "table" then
local health = player(player_id, "health") - hit_damage
if health > 0 then
parse("sethealth "..player_id.." "..health)
else
parse("customkill "..source.NAME.." \"kill\" "..player_id)
end
return 1
end
end)
function CREATURE:update()
local target
for _, player_id in pairs(shuffle(player(0, "table"))) do
if player(player_id, "health") <= 0 then return end
local distance = math.sqrt((player(player_id, "x") - self.POSITION_X) ^ 2 + (player(player_id, "y") - self.POSITION_Y) ^ 2)
if distance > self.VISION then return end
if not target or distance < target[2] then target = { player_id, distance } self.TARGET_ID = target[1] end
end
if self.TARGET_ID then
if player(self.TARGET_ID, "health") > 0 then
local distance_x, distance_y = player(self.TARGET_ID, "x") - self.POSITION_X, player(self.TARGET_ID, "y") - self.POSITION_Y
local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2)
if distance <= self.VISION then
self.MOVE_ROTATION = math.atan2(distance_y, distance_x) - math.pi / 2 + math.random(-1, 1) / 2
self.LOOK_ROTATION = math.deg(math.atan2(distance_y, distance_x)) + 90
if distance <= self.ATTACK.RANGE then msg("hit") end
else self.TARGET_ID = nil end
else self.TARGET_ID = nil end
else self:rotate(math.random(-1, 1) / 2) end
if not self:setpos(self:rotate(), self.HITPOINT > 0 and 1 or -1) then repeat until self:setpos(math.rad(math.random(360)), 1) end
end
function CREATURE:insert(creature)
creature.IMAGE = image(creature.IMAGE, creature.POSITION_X, creature.POSITION_Y, 0)
imagehitzone(creature.IMAGE, creature.HIT_MODE, -creature.HIT_ZONE / 2, -creature.HIT_ZONE / 2, creature.HIT_ZONE, creature.HIT_ZONE)
setmetatable(creature, self) self.__index = self
creature.INDEX = #CREATURE.ALIVE
table.insert(CREATURE.ALIVE, creature)
end
function CREATURE:remove()
freeimage(self.IMAGE)
table.remove(CREATURE.ALIVE, self.INDEX)
for index, creature in pairs(CREATURE.ALIVE) do creature.INDEX = index end
end
function CREATURE:setpos(rotation_angle, distance_factor)
local position_x, position_y = self.POSITION_X + -math.sin(rotation_angle) * distance_factor * self.MOVESPEED, self.POSITION_Y + math.cos(rotation_angle) * distance_factor * self.MOVESPEED
local tile_x, tile_y = math.floor(position_x / 32), math.floor(position_y / 32)
if tile(tile_x, tile_y, "walkable") and tile(tile_x, tile_y, "frame") ~= 251 then
if not self.TARGET_ID then self.LOOK_ROTATION = -math.deg(math.atan2((self.POSITION_X - position_x), (self.POSITION_Y - position_y))) end
self.POSITION_X, self.POSITION_Y = position_x, position_y
tween_move(self.IMAGE, 100, self.POSITION_X, self.POSITION_Y, self.LOOK_ROTATION)
return true
else
self:rotate(math.random(-1, 1) * 2 / math.pi)
return false
end
end
function CREATURE:rotate(rotation)
if not rotation then return self.MOVE_ROTATION else self.MOVE_ROTATION = (self.MOVE_ROTATION + rotation) % (2 * math.pi) end
end