-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.lua
170 lines (145 loc) · 5.63 KB
/
main.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
168
169
170
local grav_gun_mod = RegisterMod("GravityGun",1)
local grav_gun_item = Isaac.GetItemIdByName("Gravity Gun")
local grav_gun_entity = Isaac.GetEntityTypeByName("Gravity Gun")
grav_gun = nil
grabbed_flag = false
enemy_grabbed = nil
thrown_vector = nil
angle, counter = 0,0
function grav_gun_mod:render()
local player = Isaac.GetPlayer(0)
local aimDirection = player:GetAimDirection()
local delta_move = 8
local entities = Isaac.GetRoomEntities()
angle = math.rad(180) + math.atan((-aimDirection.Y),(-aimDirection.X))
if player:HasCollectible(grav_gun_item) then
local room = Game():GetRoom():GetDecorationSeed()
if prevroom == nil then prevroom = room end
if room ~= prevRoom then ResetGun() end
if grav_gun == nil then grav_gun = Isaac.Spawn(grav_gun_entity,0,0,Vector(player.Position.X + (math.cos(angle) * 25), player.Position.Y + (math.sin(angle) * 25)- 10),Vector(0,0),nil) end
prevRoom = room
sprite = grav_gun:GetSprite()
grav_gun.Position = Vector(player.Position.X + (math.cos(angle) * 25), player.Position.Y + (math.sin(angle) * 25) - 10);
grav_gun.SpriteRotation = math.deg(angle)
if enemy_grabbed ~= nil then
if grabbed_flag then
sprite:Play("grav_gun_charge", true)
trianglePoints = grav_gun_mod:getTrianglePoints(player.Position.X, player.Position.Y, angle, 90)
new_position_vector = trianglePoints
enemy_grabbed.Position = new_position_vector
else
if counter <= delta_move then
counter = counter + 1
enemy_grabbed.Position = lerp(enemy_grabbed.Position,thrown_vector,1/delta_move)
for i = 1, #entities do
if entities[i]:IsEnemy() and enemy_grabbed.Position:Distance(entities[i].Position) < 50 then
entities[i]:TakeDamage( (player.Damage + player.ShotSpeed * 5)/6,0, EntityRef(enemy_grabbed), 10)
end
end
else
enemy_grabbed = nil
end
end
end
else
end
--grav_gun_mod:asciiDebug(createPolygon())
end
function ResetGun()
if grav_gun~=nil then
grav_gun:Remove()
grav_gun = nil
end
end
function lerp(a,b,t)
return a + (b -a) * t
end
function grav_gun_mod:insidePolygon(point, polygon)
--Reference http://alienryderflex.com/polygon/ worked most of the time so I opted for the barycentric technique explained further in..
--https://blogs.msdn.microsoft.com/rezanour/2011/08/07/barycentric-coordinates-and-point-in-triangle-tests/
local u = polygon[2] - polygon[1]
local v = polygon[3] - polygon[1]
local w = point - polygon[1]
local vCrossW = v:Cross(w)
local vCrossU = v:Cross(u)
if w:Dot(u) < 0 then
return false
end
local uCrossW = u:Cross(w)
local uCrossV = u:Cross(v)
if(uCrossW * uCrossV < 0)then
return false
end
local r = vCrossW / uCrossV
local t = uCrossW / uCrossV
return (r + t <= 1) and polygon[1]:Distance(point) <= 200
end
function grav_gun_mod:asciiDebug(polygon)
-- DEBUG SHIT
local player = Isaac.GetPlayer(0)
local entities = Isaac.GetRoomEntities()
local debug_offset = 20
Isaac.RenderText( "angle:" .. angle , 100, 10, 255,55,55,255 )
Isaac.RenderText(player.Position.X .. ", " .. player.Position.Y, 10, debug_offset, 255, 55, 55, 255)
for i=1, #polygon do
local screenVec = Isaac.WorldToRenderPosition(polygon[i])
Isaac.RenderText("X",screenVec.X, screenVec.Y, 255,55,55,255)
end
local entities = Isaac.GetRoomEntities()
for i = 1, #entities do
if entities[i]:IsEnemy() then
local debugVec = Isaac.WorldToRenderPosition(entities[i].Position)
Isaac.RenderText(tostring(grav_gun_mod:insidePolygon(entities[i].Position,createPolygon())), debugVec.X, debugVec.Y, 255,50,50,255)
end
end
end
function createPolygon()
local player = Isaac.GetPlayer(0)
local triangleOffset = math.rad(27.5)
local radius = 250
return {player.Position, -- Have reference to self (player) to form a triangle
grav_gun_mod:getTrianglePoints(player.Position.X, player.Position.Y, (angle + triangleOffset), radius),
grav_gun_mod:getTrianglePoints(player.Position.X, player.Position.Y, (angle - triangleOffset), radius)}
end
function grav_gun_mod:getTrianglePoints(X,Y,angle_with_offset, radius)
return Vector( X + (radius * math.cos(angle_with_offset)), Y + (radius * math.sin(angle_with_offset)))
end
function grav_gun_mod:item_use()
if grabbed_flag and enemy_grabbed ~= nil then
grav_gun_mod:shoot()
else
grav_gun_mod:charge()
end
end
function grav_gun_mod:shoot()
local player = Isaac.GetPlayer(0)
local distance = 350
counter = 0
thrown_vector = Vector(enemy_grabbed.Position.X + math.cos(angle) * distance * player.ShotSpeed , enemy_grabbed.Position.Y + math.sin(angle) * distance * player.ShotSpeed)
grabbed_flag = false
end
function grav_gun_mod:charge()
local player = Isaac.GetPlayer(0)
local entities = Isaac.GetRoomEntities()
local closest_enemy = nil
local closest_distance = 200
for i=1,#entities do
if entities[i]:IsEnemy() and not entities[i]:IsBoss() and #entities > 0 then
local distance = player.Position:Distance(entities[i].Position)
if grav_gun_mod:insidePolygon(entities[i].Position, createPolygon()) then
if distance < closest_distance then
closest_enemy = entities[i]
closest_distance = distance
end
end
end
end
if closest_enemy ~= nil then
enemy_grabbed = closest_enemy
grabbed_flag = true
enemy_grabbed:AddSlowing(EntityRef(enemy_grabbed),10000, 9999, Color(10,10,10,10,10,10,10))
enemy_grabbed:AddFreeze(EntityRef(enemy_grabbed),10000)
end
end
grav_gun_mod:AddCallback(ModCallbacks.MC_POST_RENDER, grav_gun_mod.render)
grav_gun_mod:AddCallback(ModCallbacks.MC_USE_ITEM, grav_gun_mod.item_use, grav_gun_item)