-
Notifications
You must be signed in to change notification settings - Fork 0
/
npc-753.lua
167 lines (156 loc) · 5.8 KB
/
npc-753.lua
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
local npcManager = require("npcManager")
local basicEnemy = {}
local npcID = NPC_ID
local settings = {
id = npcID,
gfxwidth = 32,
gfxheight = 48,
height = 48,
nogravity = -1,
framestyle = 1,
frames = 2,
nohurt = true,
score = 3
}
npcManager.setNpcSettings(settings)
npcManager.registerHarmTypes(npcID,
{
HARM_TYPE_JUMP,
HARM_TYPE_SPINJUMP,
HARM_TYPE_LAVA
},
{
[HARM_TYPE_JUMP] = 10,
[HARM_TYPE_SPINJUMP] = 10,
[HARM_TYPE_LAVA] = 10
}
)
local STATE_WANDER = 0
local STATE_COLLIDED = 1
local STATE_CHASE = 2
local DEACCEL_RATE = 0.065
local BASE_SPEED = 3
local CHASE_SPEED = 4.5
local CHASE_COOLDOWN_TICKS = 300
local CHASE_DURATION_TICKS = 400
local YCHANGE_MINTIME = 40
local YCHANGE_MAXTIME = 80
local DIST_THRESHOLD = 200
function distance( x1, y1, x2, y2 )
return math.sqrt( (x2-x1)^2 + (y2-y1)^2 )
end
function basicEnemy.onTickEndNPC(v)
local data = v.data
local config = NPC.config[v.id]
local npcx_ctr = v.x + v.width / 2
local npcy_ctr = v.y + v.height / 2
if not data.state then
data.killeridx = -1 -- which player ended up killing this npc?
data.state = STATE_WANDER
data.direction = RNG.randomInt(0, 1)
data.speedYTimer = -1
data.speedYThreshold = RNG.randomInt(YCHANGE_MINTIME, YCHANGE_MAXTIME)
data.chaseCooldown = 0
data.chaseTime = 0
data.targetPlayer = Player.getNearest(npcx_ctr, npcy_ctr)
v.speedX = data.direction * BASE_SPEED
end
if data.targetPlayer.y < -200668 then --target player died
data.state = STATE_WANDER
v.speedX = data.direction * BASE_SPEED
end
if data.state == STATE_COLLIDED then
v.animationTimer = v.animationTimer + 1
if v.direction > data.direction then --was facing left, pushed right
v.animationFrame = v.animationFrame % config.frames
if v.animationTimer <= 1 then
v.animationFrame = (v.animationFrame + 1) % config.frames
end
--Text.print("haha", 100, 100)
elseif v.direction < data.direction then --was facing right, pushed left
v.animationFrame = v.animationFrame % config.frames + config.frames
if v.animationTimer <= 1 then
v.animationFrame = (v.animationFrame + 1) % config.frames + config.frames
end
end
local e = Effect.spawn(74,0,0)
e.x = v.x+(v.width/2)+(e.width/2)-v.speedX+RNG.random(-v.width/10,v.width/10)
e.y = v.y+v.height-e.height
v.speedX = v.speedX - (math.sign(v.speedX)*DEACCEL_RATE)
if math.abs(v.speedX) <= 0.3 then
data.state = STATE_WANDER
v.direction = RNG.random() < 0.5 and 1 or -1
data.direction = v.direction
v.speedX = v.direction * BASE_SPEED
v.speedY = 0
end
elseif data.state == STATE_WANDER then
data.chaseCooldown = math.max(0, data.chaseCooldown - 1)
--Text.print(string.format("COOLDOWN %d", data.chaseCooldown), 5, 7)
data.targetPlayer = Player.getNearest(npcx_ctr, npcy_ctr)
if distance(npcx_ctr, npcy_ctr, data.targetPlayer.x + data.targetPlayer.width, data.targetPlayer.y + data.targetPlayer.height) < DIST_THRESHOLD and data.chaseCooldown == 0 then
data.chaseTime = 0
data.state = STATE_CHASE
end
-- PLACEHOLDER THINGS TO DO WHEN NOT BEING HIT
data.speedYTimer = data.speedYTimer + 1
if data.speedYTimer == data.speedYThreshold then
v.speedY = RNG.randomInt(-1, 2)
end
if math.abs(v.speedX) <= 0.3 then
v.direction = RNG.random() < 0.5 and 1 or -1
v.speedX = v.direction * BASE_SPEED
end
end
if data.state == STATE_CHASE then
data.chaseTime = data.chaseTime + 1
if data.chaseTime >= CHASE_DURATION_TICKS then
data.state = STATE_WANDER
v.speedX = BASE_SPEED * v.direction
v.speedY = RNG.randomInt(-1, 1)
data.chaseCooldown = CHASE_COOLDOWN_TICKS
else
local xdir = data.targetPlayer.x + data.targetPlayer.width / 2 - npcx_ctr
local ydir = data.targetPlayer.y + data.targetPlayer.height / 2 - npcy_ctr
xdir = math.abs(xdir) < 32 and 0 or xdir / math.abs(xdir)
ydir = math.abs(ydir) < 32 and 0 or ydir / math.abs(ydir)
if v.collidesBlockUp then
ydir = 1
elseif v.collidesBlockBottom then
ydir = -1
end
v.speedX = CHASE_SPEED * xdir
v.speedY = CHASE_SPEED * ydir
end
end
-- Collisions with players
for _,p in ipairs(Player.getIntersecting(v.x,v.y,v.x+v.width,v.y+v.height)) do
local direction = (math.sign((p.x+(p.width/2))-(v.x+(v.width/2))))
--Text.showMessageBox(string.format("p.y %d, npc.y %d", p.y, v.y))
if p.y < v.y - v.height / 4 then
data.killeridx = p.idx
v:harm(HARM_TYPE_JUMP)
elseif p.y > v.y + v.height / 2 and p:mem(0x140, FIELD_WORD) == 0 then
p:kill()
else
SFX.play(77)
v.speedX = -4 * direction
p:mem(0x138, FIELD_FLOAT, 2.5 * direction)
data.state = STATE_COLLIDED
end
end
-- Collisions with NPCs
for _,np in ipairs(NPC.getIntersecting(v.x,v.y,v.x+v.width,v.y+v.height)) do
if np.idx ~= v.idx then
local direction = (math.sign((np.x+(np.width/2))-(v.x+(v.width/2))))
--Text.showMessageBox(string.format("np.y %d, npc.y %d", p.y, v.y))
v.speedX = -3 * direction
np:mem(0x138, FIELD_FLOAT, 100 * direction)
data.state = STATE_COLLIDED
end
end
end
function basicEnemy.onInitAPI()
npcManager.registerEvent(npcID, basicEnemy, "onTickEndNPC")
end
return basicEnemy