From 9a9f843271b16650ae2aece5ec8e9cc73e7ed413 Mon Sep 17 00:00:00 2001 From: Kevin Waldock Date: Wed, 14 Dec 2016 11:53:05 +0100 Subject: [PATCH 1/2] Updating a whole bunch of external APIs --- LuaScriptsLibExt/HealthPoint.lua | 482 ++++++++--------- LuaScriptsLibExt/bgofix.lua | 209 +++++++ LuaScriptsLibExt/bgofix/blank.png | Bin 0 -> 104 bytes LuaScriptsLibExt/booBuddies.lua | 325 +++++++++++ LuaScriptsLibExt/booBuddies/boos.png | Bin 0 -> 3533 bytes LuaScriptsLibExt/booBuddies/effect-94.png | Bin 0 -> 503 bytes LuaScriptsLibExt/characters.lua | 45 ++ LuaScriptsLibExt/colliders.lua | 509 ++++++++---------- LuaScriptsLibExt/deathTracker.lua | 102 ++++ LuaScriptsLibExt/deathTracker/arrowIcon.png | Bin 0 -> 400 bytes LuaScriptsLibExt/deathTracker/arrowIcon2x.png | Bin 0 -> 340 bytes LuaScriptsLibExt/deathTracker/cat.png | Bin 0 -> 1398 bytes LuaScriptsLibExt/deathTracker/deathIcon.png | Bin 0 -> 499 bytes LuaScriptsLibExt/deathTracker/deathIcon2x.png | Bin 0 -> 435 bytes LuaScriptsLibExt/deathTracker/player1.png | Bin 0 -> 490 bytes LuaScriptsLibExt/deathTracker/player2.png | Bin 0 -> 465 bytes LuaScriptsLibExt/deathTracker/player3.png | Bin 0 -> 549 bytes LuaScriptsLibExt/deathTracker/player4.png | Bin 0 -> 514 bytes LuaScriptsLibExt/deathTracker/player5.png | Bin 0 -> 659 bytes LuaScriptsLibExt/deathTracker/sweat smile.png | Bin 0 -> 1351 bytes LuaScriptsLibExt/deathTracker/trump.png | Bin 0 -> 2559 bytes LuaScriptsLibExt/debug.lua | 68 +++ LuaScriptsLibExt/eventu.lua | 101 +++- LuaScriptsLibExt/metaluna.lua | 84 +++ LuaScriptsLibExt/npcParse.lua | 278 ++++++++++ LuaScriptsLibExt/raocoin2.lua | 32 +- LuaScriptsLibExt/smoovement.lua | 229 ++++++++ LuaScriptsLibExt/vectr.lua | 203 ++++--- .../.idea/LunaLuaBindingsGenerator.iml | 14 + Tools/LunaLuaBindingsGenerator/.idea/misc.xml | 14 + .../.idea/modules.xml | 8 + .../.idea/workspace.xml | 266 +++++++++ 32 files changed, 2328 insertions(+), 641 deletions(-) create mode 100644 LuaScriptsLibExt/bgofix.lua create mode 100644 LuaScriptsLibExt/bgofix/blank.png create mode 100644 LuaScriptsLibExt/booBuddies.lua create mode 100644 LuaScriptsLibExt/booBuddies/boos.png create mode 100644 LuaScriptsLibExt/booBuddies/effect-94.png create mode 100644 LuaScriptsLibExt/characters.lua create mode 100644 LuaScriptsLibExt/deathTracker.lua create mode 100644 LuaScriptsLibExt/deathTracker/arrowIcon.png create mode 100644 LuaScriptsLibExt/deathTracker/arrowIcon2x.png create mode 100644 LuaScriptsLibExt/deathTracker/cat.png create mode 100644 LuaScriptsLibExt/deathTracker/deathIcon.png create mode 100644 LuaScriptsLibExt/deathTracker/deathIcon2x.png create mode 100644 LuaScriptsLibExt/deathTracker/player1.png create mode 100644 LuaScriptsLibExt/deathTracker/player2.png create mode 100644 LuaScriptsLibExt/deathTracker/player3.png create mode 100644 LuaScriptsLibExt/deathTracker/player4.png create mode 100644 LuaScriptsLibExt/deathTracker/player5.png create mode 100644 LuaScriptsLibExt/deathTracker/sweat smile.png create mode 100644 LuaScriptsLibExt/deathTracker/trump.png create mode 100644 LuaScriptsLibExt/debug.lua create mode 100644 LuaScriptsLibExt/metaluna.lua create mode 100644 LuaScriptsLibExt/npcParse.lua create mode 100644 LuaScriptsLibExt/smoovement.lua create mode 100644 Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml create mode 100644 Tools/LunaLuaBindingsGenerator/.idea/misc.xml create mode 100644 Tools/LunaLuaBindingsGenerator/.idea/modules.xml create mode 100644 Tools/LunaLuaBindingsGenerator/.idea/workspace.xml diff --git a/LuaScriptsLibExt/HealthPoint.lua b/LuaScriptsLibExt/HealthPoint.lua index 392f5b732..678f4d5d0 100644 --- a/LuaScriptsLibExt/HealthPoint.lua +++ b/LuaScriptsLibExt/HealthPoint.lua @@ -1,7 +1,7 @@ -- HealthPoint -- Made by WasabiJellyfish -- v1.0.3 - + local HealthPoint = {} local pNPC = loadSharedAPI("pnpc") local graphX = loadSharedAPI("graphX") @@ -9,49 +9,49 @@ local colliders = loadSharedAPI("colliders") function HealthPoint.onInitAPI() --Is called when the api is loaded by loadAPI. registerEvent(HealthPoint, "onLoop", "assign", true) --Register the loop event - registerEvent(HealthPoint, "onNPCKill", "onNPCKill", true) --Register the damage event + registerEvent(HealthPoint, "onNPCKill", "onNPCKill", true) --Register the damage event end ---------------------------------------------------------------------------------------------- --- DOCUMENTATION AND FUNCTIONS --- ---------------------------------------------------------------------------------------------- --[[ - Damage types + Damage types 1 = jump - 2 = spinjump - 3 = fireball - 4 = hammer - 5 = shell - 6 = tail - 7 = link - 8 = thrown - 9 = boomerang - 10 = peachbomb - 11 = swordbeam - 12 = linkfire - 13 = iceblock - 14 = yoshifire - 15 = yoshiice - - HealthPoint.setNPCHealth(id, healthamount) + 2 = spinjump + 3 = fireball + 4 = hammer + 5 = shell + 6 = tail + 7 = link + 8 = thrown + 9 = boomerang + 10 = peachbomb + 11 = swordbeam + 12 = linkfire + 13 = iceblock + 14 = yoshifire + 15 = yoshiice + + HealthPoint.setNPCHealth(id, healthamount) - HealthPoint.setNPCDamage(id, damagetype, damageamount) + HealthPoint.setNPCDamage(id, damagetype, damageamount) - HealthPoint.setGlobalDamage(damagetype, damageamount) + HealthPoint.setGlobalDamage(damagetype, damageamount) - HealthPoint.makeNPCInvincible(id) + HealthPoint.makeNPCInvincible(id) - HealthPoint.makeNPCNormal(id) + HealthPoint.makeNPCNormal(id) --]] ---------------------------------------------------------------------------------------------- --- THE ACTUAL CODE STUFF --- ---------------------------------------------------------------------------------------------- - + local bingo = {1, 2, 3, 4, 5, 6, 7, 8, 12, 15, 17, 18, 19, 20, 23, 24, 25, 27, 28, 29, 36, 37, 38, 39, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, 59, 61, 63, 65, 71, 72, 73, 74, 76, 77, 86, 89, 93, 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, 135, 136, 137, 161, 162, 163, 164, 165, 166, 167, 168, 172, 173, 174, 175, 176, 177, 180, 189, 194, 195, 199, 200, 201, 203, 204, 205, 206, 207, 208, 209, 210, 229, 230, 231, 232, 233, 234, 235, 236, 242, 243, 244, 245, 247, 256, 257, 261, 262, 263, 267, 268, 270, 271, 272, 275, 280, 281, 284, 285, 286} -- Health -- -- Change these values corresponding to the id inside the [] to change the enemy's health -- @@ -59,7 +59,7 @@ local bingo = {1, 2, 3, 4, 5, 6, 7, 8, 12, 15, 17, 18, 19, 20, 23, 24, 25, 27, 2 for _,v in pairs(bingo) do table.insert(HealthPoint.npcHealth, v, 3) end - + -- Jump Damage -- HealthPoint.jumpDamage = {} @@ -71,7 +71,7 @@ local bingo = {1, 2, 3, 4, 5, 6, 7, 8, 12, 15, 17, 18, 19, 20, 23, 24, 25, 27, 2 for _,v in pairs(bingo) do table.insert(HealthPoint.spinjumpDamage, v, 1) end - + -- Fireball Damage -- HealthPoint.fireballDamage = {} for _,v in pairs(bingo) do @@ -83,47 +83,47 @@ local bingo = {1, 2, 3, 4, 5, 6, 7, 8, 12, 15, 17, 18, 19, 20, 23, 24, 25, 27, 2 for _,v in pairs(bingo) do table.insert(HealthPoint.hammerDamage, v, 1) end - + -- Projectile Damage -- HealthPoint.projectileDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.projectileDamage, v, 1) end - + -- Tail Damage -- HealthPoint.tailDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.tailDamage, v, 1) end - + -- Link Attack Damage -- HealthPoint.linkDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.linkDamage, v, 1) end - + -- Thrown Damage -- HealthPoint.thrownDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.thrownDamage, v, 1) end - + -- Boomerang Damage-- HealthPoint.boomerangDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.boomerangDamage, v, 1) end - + HealthPoint.peachbombDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.peachbombDamage, v, 1) end - + HealthPoint.swordbeamDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.swordbeamDamage, v, 1) end - + HealthPoint.yoshifireDamage = {} for _,v in pairs(bingo) do table.insert(HealthPoint.yoshifireDamage, v, 1) @@ -171,7 +171,7 @@ end for l,_ in pairs(HealthPoint.npcHealth) do damevaeg[cause][l] = number end - end + end function HealthPoint.makeNPCInvincible(id) for r,_ in pairs(damevaeg) do @@ -190,216 +190,216 @@ end ---------------------------------------------------------------------------------------------- function HealthPoint.onNPCKill(eventObj, killedNPC, killReason) - if killedNPC.id == 13 and killReason == 4 then - fire = true - hammer = false - shell = false - end - if HealthPoint.npcHealth[killedNPC.id] ~= nil then - local wrappedNPC = pNPC.wrap(killedNPC) - - - if colliders.collideNPC(wrappedNPC, 171) then - hammer = true - fire = false - shell = false - elseif colliders.collideNPC(wrappedNPC, 292) then - boomerang = true - hammer = false - fire = false - shell = false - elseif colliders.collideNPC(wrappedNPC, 108) then - yoshifire = true - hammer = false - fire = false - shell = false - - elseif colliders.collideNPC (wrappedNPC, 263) then - Text.print ("ICE", 100, 100) - ice = true - shell = false - hammer = false - fire = false - - elseif colliders.collideNPC (wrappedNPC, 291) then - peachbomb = true - shell = false - - elseif colliders.collideNPC (wrappedNPC, 266) then - laser = true - shell = false - elseif colliders.collideNPC(wrappedNPC, 237) then - yoshiice = true - shell = false - else - shell = true - - end - - - if wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.jumpDamage[wrappedNPC.id] and killReason == 1 then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.jumpDamage[wrappedNPC.id] - playSFX(2) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.fireballDamage[wrappedNPC.id] and killReason == 3 and fire then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.fireballDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - fire = false - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.iceblockDamage[wrappedNPC.id] and killReason == 3 and ice then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.iceblockDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.hammerDamage[wrappedNPC.id] and killReason == 3 and hammer then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.hammerDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.boomerangDamage[wrappedNPC.id] and killReason == 3 and boomerang then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.boomerangDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.yoshifireDamage[wrappedNPC.id] and killReason == 3 and yoshifire then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.yoshifireDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.yoshifireDamage[wrappedNPC.id] and killReason == 3 and yoshiice then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.yoshiiceDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.peachbombDamage[wrappedNPC.id] and killReason == 3 and peachbomb then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.peachbombDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.swordbeamDamage[wrappedNPC.id] and killReason == 10 and laser then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.swordbeamDamage[wrappedNPC.id] - playSFX(89) - wrappedNPC.speedX = 0 - - - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.projectileDamage[wrappedNPC.id] and killReason == 3 and shell and not fire and not ice then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.projectileDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - shell = false - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.thrownDamage[wrappedNPC.id] and (killReason == 4 or killReason == 5) then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.thrownDamage[wrappedNPC.id] - - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.tailDamage[wrappedNPC.id] and killReason == 7 then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.tailDamage[wrappedNPC.id] - playSFX(3) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.spinjumpDamage[wrappedNPC.id] and killReason == 8 then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.spinjumpDamage[wrappedNPC.id] - playSFX(2) - wrappedNPC.speedX = 0 - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.linkDamage[wrappedNPC.id] and killReason == 10 and not fire then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.linkDamage[wrappedNPC.id] - playSFX(89) - wrappedNPC.speedX = 0 - - - elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.linkfireDamage[wrappedNPC.id] and killReason == 10 and fire then - eventObj.cancelled = true - wrappedNPC:mem(0x156, FIELD_WORD, 20) - wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.linkfireDamage[wrappedNPC.id] - playSFX(89) - wrappedNPC.speedX = 0 - - end - end + if killedNPC.id == 13 and killReason == 4 then + fire = true + hammer = false + shell = false + end + if HealthPoint.npcHealth[killedNPC.id] ~= nil then + local wrappedNPC = pNPC.wrap(killedNPC) + + + if colliders.collideNPC(wrappedNPC, 171) then + hammer = true + fire = false + shell = false + elseif colliders.collideNPC(wrappedNPC, 292) then + boomerang = true + hammer = false + fire = false + shell = false + elseif colliders.collideNPC(wrappedNPC, 108) then + yoshifire = true + hammer = false + fire = false + shell = false + + elseif colliders.collideNPC (wrappedNPC, 263) then + Text.print ("ICE", 100, 100) + ice = true + shell = false + hammer = false + fire = false + + elseif colliders.collideNPC (wrappedNPC, 291) then + peachbomb = true + shell = false + + elseif colliders.collideNPC (wrappedNPC, 266) then + laser = true + shell = false + elseif colliders.collideNPC(wrappedNPC, 237) then + yoshiice = true + shell = false + else + shell = true + + end + + + if wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.jumpDamage[wrappedNPC.id] and killReason == 1 then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.jumpDamage[wrappedNPC.id] + playSFX(2) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.fireballDamage[wrappedNPC.id] and killReason == 3 and fire then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.fireballDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + fire = false + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.iceblockDamage[wrappedNPC.id] and killReason == 3 and ice then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.iceblockDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.hammerDamage[wrappedNPC.id] and killReason == 3 and hammer then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.hammerDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.boomerangDamage[wrappedNPC.id] and killReason == 3 and boomerang then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.boomerangDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.yoshifireDamage[wrappedNPC.id] and killReason == 3 and yoshifire then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.yoshifireDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.yoshifireDamage[wrappedNPC.id] and killReason == 3 and yoshiice then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.yoshiiceDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.peachbombDamage[wrappedNPC.id] and killReason == 3 and peachbomb then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.peachbombDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.swordbeamDamage[wrappedNPC.id] and killReason == 10 and laser then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.swordbeamDamage[wrappedNPC.id] + playSFX(89) + wrappedNPC.speedX = 0 + + + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.projectileDamage[wrappedNPC.id] and killReason == 3 and shell and not fire and not ice then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.projectileDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + shell = false + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.thrownDamage[wrappedNPC.id] and (killReason == 4 or killReason == 5) then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.thrownDamage[wrappedNPC.id] + + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.tailDamage[wrappedNPC.id] and killReason == 7 then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.tailDamage[wrappedNPC.id] + playSFX(3) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.spinjumpDamage[wrappedNPC.id] and killReason == 8 then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.spinjumpDamage[wrappedNPC.id] + playSFX(2) + wrappedNPC.speedX = 0 + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.linkDamage[wrappedNPC.id] and killReason == 10 and not fire then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.linkDamage[wrappedNPC.id] + playSFX(89) + wrappedNPC.speedX = 0 + + + elseif wrappedNPC.data.hit > 1 and wrappedNPC.data.hit > HealthPoint.linkfireDamage[wrappedNPC.id] and killReason == 10 and fire then + eventObj.cancelled = true + wrappedNPC:mem(0x156, FIELD_WORD, 20) + wrappedNPC.data.hit = wrappedNPC.data.hit - HealthPoint.linkfireDamage[wrappedNPC.id] + playSFX(89) + wrappedNPC.speedX = 0 + + end + end end - - - + + + ---------------------------------------------------------------------------------------------- --- HEALTH ASSIGNMENT --- ---------------------------------------------------------------------------------------------- function HealthPoint.assign() - for k,v in pairs(NPC.get()) do - - local n = pNPC.wrap(v); - - if n.data.hit == nil then - if HealthPoint.npcHealth[n.id] ~= nil then - n.data.hit = HealthPoint.npcHealth[n.id] - - end - end - - if n.data.hp == nil then - if HealthPoint.npcHealth[n.id] ~= nil then - n.data.hp = HealthPoint.npcHealth[n.id] - - end - end - - if n.data.hpmax == nil then - if HealthPoint.npcHealth[n.id] ~= nil then - n.data.hpmax = HealthPoint.npcHealth[n.id] - end - end - - if n ~= nil and HealthPoint.healthbar then - if n:mem(0x12A, FIELD_WORD) ~= 0 and n.data.hp ~= nil then - graphX.boxLevel (n.x-8,n.y-6, 32, 8, 0xFFFFFFF55) - graphX.boxLevel (n.x-7,n.y-5, 30, 6, 0x00000055) - graphX.boxLevel (n.x-7,n.y-5, n.data.hp/n.data.hpmax*30, 6, 0xFFF05BFF) - graphX.boxLevel (n.x-7,n.y-5, n.data.hit/n.data.hpmax*30, 6, 0xF61818FF) - - end - end - - if n.data.hp ~= nil then - if n.data.hp > n.data.hit then - n.data.hp = n.data.hp -0.02 - end - if n.data.hit > n.data.hpmax then - n.data.hit = n.data.hpmax - end - end - end + for k,v in pairs(NPC.get()) do + + local n = pNPC.wrap(v); + + if n.data.hit == nil then + if HealthPoint.npcHealth[n.id] ~= nil then + n.data.hit = HealthPoint.npcHealth[n.id] + + end + end + + if n.data.hp == nil then + if HealthPoint.npcHealth[n.id] ~= nil then + n.data.hp = HealthPoint.npcHealth[n.id] + + end + end + + if n.data.hpmax == nil then + if HealthPoint.npcHealth[n.id] ~= nil then + n.data.hpmax = HealthPoint.npcHealth[n.id] + end + end + + if n ~= nil and HealthPoint.healthbar then + if n:mem(0x12A, FIELD_WORD) ~= 0 and n.data.hp ~= nil then + graphX.boxLevel (n.x-8,n.y-6, 32, 8, 0xFFFFFFF55) + graphX.boxLevel (n.x-7,n.y-5, 30, 6, 0x00000055) + graphX.boxLevel (n.x-7,n.y-5, n.data.hp/n.data.hpmax*30, 6, 0xFFF05BFF) + graphX.boxLevel (n.x-7,n.y-5, n.data.hit/n.data.hpmax*30, 6, 0xF61818FF) + + end + end + + if n.data.hp ~= nil then + if n.data.hp > n.data.hit then + n.data.hp = n.data.hp -0.02 + end + if n.data.hit > n.data.hpmax then + n.data.hit = n.data.hpmax + end + end + end end - return HealthPoint + return HealthPoint \ No newline at end of file diff --git a/LuaScriptsLibExt/bgofix.lua b/LuaScriptsLibExt/bgofix.lua new file mode 100644 index 000000000..7a13f0f17 --- /dev/null +++ b/LuaScriptsLibExt/bgofix.lua @@ -0,0 +1,209 @@ +--***************************************************************************-- +--*██████╗ ██████╗ ██████╗ ███████╗██╗██╗ ██╗ ██╗ ██╗ ██╗ █████╗ *-- +--*██╔══██╗██╔════╝ ██╔═══██╗██╔════╝██║╚██╗██╔╝ ██║ ██║ ██║██╔══██╗*-- +--*██████╔╝██║ ███╗██║ ██║█████╗ ██║ ╚███╔╝ ██║ ██║ ██║███████║*-- +--*██╔══██╗██║ ██║██║ ██║██╔══╝ ██║ ██╔██╗ ██║ ██║ ██║██╔══██║*-- +--*██████╔╝╚██████╔╝╚██████╔╝██║ ██║██╔╝ ██╗██╗███████╗╚██████╔╝██║ ██║*-- +--*╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝*-- +--***************************************************************************-- +--* A small library for rendering BGOs of custom sizes and changing render order +--* Coded by Sambo, Oct. 2016. +--* NOTE: You must use PNG CGFX for this to work. LunaLua currently doesn't support drawing of masked GIFs. +--***************************************************************************-- + +local bgofix = {} + +local defaults = {} +defaults.foreground = {23,24,25,36,45,46,49,50,51,68,69,187,188,189,190} +defaults.veryBackBgos = {11,12,75,76,77,78,79} +defaults.specialBGOs = {98,160} + +local bgos = {} -- Table of unique BGO IDs and their custom properties +local blank = Graphics.loadImage(Misc.resolveFile("bgofix/blank.png")) +local animData = {} + +function bgofix.onInitAPI() + registerEvent(bgofix, "onStart", "initialize") + registerEvent(bgofix, "onDraw", "draw") +end + +--[[******************************************** + * Load the custom image for each BGO if it exists in .PNG format + * This will rather redundantly reload images that are already in the memory of SMBX; however, there is no workaround for this issue right now. + ********************************************]] +local function loadImg(id) + local imageName = Misc.resolveFile("background-" .. id .. ".png") -- Search level and episode directorties + local image; + if imageName then + image = Graphics.loadImage(imageName) + end + if image then return image; + else return nil; end; +end + +--[[******************************************** + * Set the given BGO to be drawn over if a valid custom image exists + * and it is larger than the original in either dimension. + ********************************************]] +local function setShouldDraw(bgo, image) + if image then + if (image.width ~= bgo.width) or (image.height ~= image.height) then + return true; + else + return false; + end + end +end + +--[[******************************************** + * Get the default render priority for the BGO with the given ID + ********************************************]] +local function getDefault(id) -- Test sets from most likely to least likely, except for the largest set, to avoid as many tests as possible. + for _,v in pairs(defaults.foreground) do + if id == v then + return -20; + end + end + for _,v in pairs(defaults.veryBackBgos) do + if id == v then + return -95; + end + end + for _,v in pairs(defaults.specialBGOs) do + if id == v then + return -80; + end + end + return -85; +end + +--[[******************************************** + * Set the render priority to the default value or to a custom value inputted by the user + * Note: This uses LunaLua render priorities, which are not equivalent to SMBX sort-order priorities! + * This could change the render order from how it is normally. If this occurs, use setPriority to fix it. + * This will only work if called in onStart! + ********************************************]] +function bgofix.setPriority(id, priority) + assert(bgos[id].image, "Cannot change the render priority of BGO-" .. id .. " because it doesn't have a .PNG custom image.") -- Make sure the user didn't break the rules. + if (priority) and not (bgos[id].shouldDraw) then + bgos[id].shouldDraw = true -- Handling for the user changing the render priority of BGOs which are the same size as the original + end + + bgos[id].priority = priority or getDefault(id) -- fetch default setting if custom setting is not given. + Graphics.sprites.background[id].img = blank -- Make the actual BGO invisible. This is to allow the user to make the BGO's render priority lower. +end + +--[[******************************************** + * Resize the given BGO to have the same dimensions as its image + ********************************************]] +local function resize(bgo, image) + if ((image) and (bgo.width ~= image.width or bgo.height ~= image.height)) then + bgo.width = image.width + bgo.height = image.height + end +end + +--[[******************************************** + * Initialization + ********************************************]] +function bgofix.initialize() + + for _,bgo in ipairs(BGO.get()) do + if not bgos[bgo.id] then -- Do this only once for each BGO with a unique ID. + bgos[bgo.id] = {} + bgos[bgo.id].image = loadImg(bgo.id) -- custom image (nil if no valid image) + bgos[bgo.id].shouldDraw = setShouldDraw(bgo, bgos[bgo.id].image); -- Does the BGO need to be rendered over? + + + if bgos[bgo.id].shouldDraw then + bgofix.setPriority(bgo.id) -- LunaLua render priority + end + + end + + if bgos[bgo.id] then + resize(bgo, bgos[bgo.id].image); + end + + end +end + +--[[******************************************** + * Get all BGOs on the screen + * This is why I bothered to resize any BGOs so they were bigger. + * If I hadn't done this, BGOs that still appeared to be onscreen would disappear because the object isn't on the screen. + ********************************************]] +local function getBgosOnScreen() + local bgosOnScreen = {} + for _,cam in pairs(Camera.get()) do -- Check this way so it works in 2P mode + for __,bgo in pairs(BGO.getIntersecting(cam.x, cam.y, cam.x + cam.width, cam.y + cam.height)) do + if not bgo.isHidden then -- Don't insert BGOs that are on hidden layers! + table.insert(bgosOnScreen, bgo) + end + end + end + return bgosOnScreen; +end + +--[[******************************************** + * Set a custom animation + * Animation image is a separate image from the BGO image with the naming style "bgo-anim-*.png," where '*' is the ID of the BGO. + * This may seem like a weird way to do it, but it is so they will display better in the PGE editor. + ********************************************]] +function bgofix.setAnimation(id, numFrames, frameSpeed) + + if not bgos[id].shouldDraw then + bgos[id].shouldDraw = true + bgos[id].priority = getDefault(id) + Graphics.sprites.background[id].img = blank + end + + animData[id] = {} + + local imageName = Misc.resolveFile("bgo-anim-" .. id .. ".png") + if imageName then + animData[id].image = Graphics.loadImage(imageName) + else + error("Animation image for background-" .. id .. " not found.") + end + + animData[id].frames = numFrames or 4 + animData[id].frameSpeed = frameSpeed or 8 -- The number of ticks per frame for the BGO. Default = 8 + animData[id].frame = 0 -- Current frame. Reset to 0 when this == numFrames - 1 + animData[id].tick = 0 -- Tick counter. Reset to 0 and move to the next frame when this == frameSpeed + + assert(animData[id].frames > 0, "Invalid number of frames for BGO-" .. id .. ". Value must be greater than 0.") + assert(animData[id].frameSpeed > 0, "Invalid frame speed value for BGO-" .. id .. ". Value must be greater than 0.") +end + +--[[******************************************** + * Update the frame numbers of the BGOs with custom animations + ********************************************]] +local function updateAnimations() + for id,_ in pairs(animData) do + -- Compact frame controller + -- Why doesn't anyone use the modulus operator?? + animData[id].frame = math.floor(animData[id].tick / animData[id].frameSpeed) + animData[id].tick = (animData[id].tick + 1) % (animData[id].frames * animData[id].frameSpeed) + end +end + +--[[******************************************** + * Draw over the BGOs that are on the screen + ********************************************]] +function bgofix.draw() + -- Draw all BGOs on the screen that are listed for drawing + for _,bgo in pairs(getBgosOnScreen()) do + if bgos[bgo.id].shouldDraw then + if animData[bgo.id] then -- Draw animations for BGOs that have them + Graphics.drawImageToSceneWP(animData[bgo.id].image, bgo.x, bgo.y, 0, bgo.height * animData[bgo.id].frame, bgo.width, bgo.height, bgos[bgo.id].priority) + -- image position source image position dimensions priority + else + Graphics.drawImageToSceneWP(bgos[bgo.id].image, bgo.x, bgo.y, bgos[bgo.id].priority) + end + end + end + updateAnimations(); +end + +return bgofix \ No newline at end of file diff --git a/LuaScriptsLibExt/bgofix/blank.png b/LuaScriptsLibExt/bgofix/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..65b943f847a37bb73f2810d2f307ab42d88b3f92 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?5OL=a|NVZS^RC@AIW t;usRq`t~3rBaqjm@PB=thXaWDo=rf3fzh3DK?jh-;OXk;vd$@?2>=$B7K8u* literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/booBuddies.lua b/LuaScriptsLibExt/booBuddies.lua new file mode 100644 index 000000000..0b79e5344 --- /dev/null +++ b/LuaScriptsLibExt/booBuddies.lua @@ -0,0 +1,325 @@ +--booBuddies.lua +--v1.0.2 +--Created by S1eth, 2016 + +local colliders = API.load("colliders"); + +local booBuddies = {}; + +function booBuddies.onInitAPI() + registerEvent(booBuddies, "onTick", "onTick", true); --Register the loop event + registerEvent(booBuddies, "onDraw", "onDraw", true); --Register the draw event +end + + +--*************************************************************************************************** +-- * +-- UTILITY FUNCTIONS * +-- * +--*************************************************************************************************** + +local function round(x) + return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5); +end + +-- Finds the corresponding section for a point (x,y). (If the point is within 1000 pixel of the section boundary) +local function getSection(x, y) + for index,section in pairs(Section.get()) do + local boundary = section.boundary; + local sectionBox = colliders.Box( + boundary.left - 1000, + boundary.top - 1000, + boundary.right - boundary.left + 1000, + boundary.bottom - boundary.top + 1000 + ) + + if colliders.collide(sectionBox, colliders.Point(x, y)) then + return index-1; -- one-indexed --> zero-indexed + end + end + + return nil; +end + + +--*************************************************************************************************** +-- * +-- PRIVATE CONSTANTS * +-- * +--*************************************************************************************************** + +-- boo types used in SMW's boo buddies +local BOO_TYPES_SMW = {0, 1, 2, 0}; --repeats when more than 4 boos are used + +-- load spritesheet for the boos +local BOO_IMAGE_RESOURCE = Graphics.loadImage(Misc.resolveFile("booBuddies/boos.png")); + +local MOUNT_TYPES = {shoe = 1, yoshi = 3}; + +local style = {SMW = 0, SMB3 = 1, SMB1 = 2, SMM_SMW = 3}; + +local direction = {right = 0, left = 1}; + +local angularDirection = {clockwise = 1, CW = 1, counterclockwise = -1, CCW = -1}; + +local _preset = {}; +_preset.SMW = {}; +_preset.SMW.style = "SMW"; +_preset.SMW.numberOfBoos = 10; +_preset.SMW.booSpacing = 0.483321947; +_preset.SMW.circleRadius = 5 * 32; +_preset.SMW.angularSpeed = math.pi / 275; +_preset.SMW.angularDirection = angularDirection.clockwise; + +_preset.SMM = {}; +_preset.SMM.style = "SMM_SMW"; +_preset.SMM.numberOfBoos = 8; +_preset.SMM.booSpacing = math.pi / 4.5; +_preset.SMM.circleRadius = 3 * 32; +_preset.SMM.angularSpeed = math.pi / 240; +_preset.SMM.angularDirection = angularDirection.clockwise; + + +--*************************************************************************************************** +-- * +-- PUBLIC MEMBERS * +-- * +--*************************************************************************************************** + +booBuddies.diesTo = {shoe = false, starman = false}; + +booBuddies.booNPCID = {SMW = 43, SMB3 = 38, SMB1 = 38, SMM_SMW = 43} + +booBuddies.canSpinjump = false; + +--*************************************************************************************************** +-- * +-- CLASS: Boo * +-- * +--*************************************************************************************************** + +local Boo = {}; +Boo.__index = Boo; +Boo.isAlive = true; + +function Boo.create() + local newInstance = {}; + setmetatable(newInstance, Boo); + + return newInstance; +end + +-- get the graphic rectangle for a specific boo animation frame +function getBooRectangle(styleIndex, direction, booIndex, frameIndex) + local rectangle = { width = 32, height = 32}; + rectangle.left = style[styleIndex] * 96 + ((styleIndex == "SMW") and booIndex * 32 or 0); -- only SMW has multiple boo types (for now?) + rectangle.top = direction * 64 + ((styleIndex == "SMW") and frameIndex * 32 or 0); -- only SMW has animation frames (for now?) + return rectangle; +end + +--*************************************************************************************************** +-- * +-- CLASS: BooCircle * +-- * +--*************************************************************************************************** + +local booCircleTable = {}; + +local BooCircle = {} +BooCircle.__index = BooCircle; +BooCircle.isActive = false; +BooCircle.toBeDeleted = false; +BooCircle.toBeKilled = false; +BooCircle.initial = {}; + +function BooCircle.create(args) + local newInstance = {} -- our new object + setmetatable (newInstance, BooCircle) -- make BooCircle handle lookup + + local preset; + if(args.preset == nil) then + preset = _preset.SMW; + else + assert(_preset[args.preset] ~= nil, "preset "..args.preset.." does not exist"); + preset = _preset[args.preset]; + end + + newInstance.style = args.style or preset.style; + + assert(args.x ~= nil and type(args.x) == "number", "x coordinate must be a number"); + assert(args.y ~= nil and type(args.y) == "number", "y coordinate must be a number"); + newInstance.x = args.x + newInstance.y = args.y + + newInstance.section = args.section or getSection(newInstance.x,newInstance.y); + newInstance.layer = args.layer or "Default"; + + newInstance.circleRadius = args.circleRadius or preset.circleRadius; + newInstance.angularSpeed = args.angularSpeed or preset.angularSpeed; + newInstance.angularDirection = angularDirection[args.angularDirection] or preset.angularDirection; + newInstance.numberOfBoos = args.numberOfBoos or preset.numberOfBoos; + newInstance.booRadius = args.booRadius or 10; + newInstance.frameTime = args.frameTime or 8; + newInstance.frame = args.frame or 0; + newInstance.booSpacing = args.booSpacing or preset.booSpacing; + newInstance.angle = args.angle or math.pi*1.5 - (newInstance.booSpacing * (newInstance.numberOfBoos-1)/2); + + -- reset to these initial values when entering/leaving a section + newInstance.initial.angle = newInstance.angle; + newInstance.initial.frame = newInstance.frame; + + newInstance.boos = {}; + for i=1,newInstance.numberOfBoos,1 do + table.insert(newInstance.boos, Boo.create(booBuddies.diesTo)); + end + + table.insert (booCircleTable, newInstance) + return newInstance; +end + +function BooCircle:update() + + -- Deactivate if not on a visible layer or current section + -- reset the cycle + if Layer.get(self.layer).isHidden + or not(player.section == self.section + or (player2 ~= nil and player2.section == self.section)) + then + if (self.isActive) then + self.isActive = false; + self.angle = self.initial.angle; + self.frame = self.initial.frame; + end + return; + end + + -- Reactivate + if not self.isActive then + self.isActive = true; + end + + --update position + self.angle = self.angle + self.angularSpeed * self.angularDirection; + self.frame = (self.frame + 1) % (self.frameTime * 2); + + --check collision with player + for i,boo in pairs(self.boos) do + + if(boo.isAlive) then + local booX = round(self.x + self.circleRadius * math.cos(self.angle + (i-1) * self.booSpacing)); + local booY = round(self.y + self.circleRadius * math.sin(self.angle + (i-1) * self.booSpacing)); + + local hitbox = colliders.Circle(booX, booY, self.booRadius); + for _,p in pairs({player, player2}) do + + local bounce, spinjump = colliders.bounce(p,hitbox); + local downSlash = colliders.downSlash(p,hitbox); + + if(bounce and p.DeathTimer == 0 and not inStar) then + if(booBuddies.canSpinjump and (spinjump or downSlash or p.MountType == MOUNT_TYPES.yoshi or p.MountType == MOUNT_TYPES.shoe) ) then + colliders.bounceResponse(p); + if(p.MountType == MOUNT_TYPES.shoe and booBuddies.diesTo["shoe"]) then + self:killBoo(boo, booX, booY); + end + else + p:harm(); + end + elseif(colliders.collide(p,hitbox)) then + --check for starman + if(booBuddies.diesTo["starman"] and inStar) then + self:killBoo(boo, booX, booY); + else + p:harm(); + end + end + + end + end + end -- for i,boo in pairs(self.boos) + +end -- BooCircle:update() + +function BooCircle:draw() + + if not self.isActive then return end + + for i,boo in pairs(self.boos) do + if(boo.isAlive) then + local booX = round(self.x + self.circleRadius * math.cos(self.angle + (i-1) * self.booSpacing)); + local booY = round(self.y + self.circleRadius * math.sin(self.angle + (i-1) * self.booSpacing)); + + local dir = direction.right; + if(self.style ~= "SMW") and (player.x + player.width/2 < booX) then + dir = direction.left; + end + + local booRect; + if (self.frame < self.frameTime) then + booRect = getBooRectangle(self.style, dir, BOO_TYPES_SMW[1+((i-1) % 4)], 0); + else + booRect = getBooRectangle(self.style, dir, BOO_TYPES_SMW[1+((i-1) % 4)], 1); + end + + Graphics.drawImageToSceneWP(BOO_IMAGE_RESOURCE, booX-16, booY-16, booRect.left, booRect.top, booRect.width, booRect.height, -45.0); + end + end -- for i,boo in pairs(self.boos) + +end -- BooCircle:draw() + +function BooCircle:delete() + self.toBeDeleted = true; -- delete during next onTick() +end + +function BooCircle:kill() + self.toBeKilled = true; -- kill during next onTick() +end + +function BooCircle:killBoos() + for i,boo in pairs(self.boos) do + if(boo.isAlive) then + local booX = round(self.x + self.circleRadius * math.cos(self.angle + (i-1) * self.booSpacing)); + local booY = round(self.y + self.circleRadius * math.sin(self.angle + (i-1) * self.booSpacing)); + + self:killBoo(boo, booX, booY); + end + end -- for i,boo in pairs(self.boos) +end + +function BooCircle:killBoo(boo, x, y) + boo.isAlive = false; + + NPC.spawn(booBuddies.booNPCID[self.style], x-16, y-16, self.section):kill(); +end + +function booBuddies.create(args) + return BooCircle.create(args); +end + +function booBuddies.onTick() + + --delete circles with the toBeKilled flag + for i=#booCircleTable,1,-1 do + if(booCircleTable[i].toBeKilled == true) then + booCircleTable[i]:killBoos(); + end + end + + --delete instances with the toBeDeleted flag + for i=#booCircleTable,1,-1 do + if(booCircleTable[i].toBeDeleted == true) then + table.remove(booCircleTable, i); + end + end + + for _,booCircle in pairs (booCircleTable) do + booCircle:update(); + end +end + +function booBuddies.onDraw() + for _,booCircle in pairs (booCircleTable) do + booCircle:draw(); + end +end + +return booBuddies; \ No newline at end of file diff --git a/LuaScriptsLibExt/booBuddies/boos.png b/LuaScriptsLibExt/booBuddies/boos.png new file mode 100644 index 0000000000000000000000000000000000000000..7d80ce7d7cf301f2fbf429c7447817bbc2c44697 GIT binary patch literal 3533 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 literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/booBuddies/effect-94.png b/LuaScriptsLibExt/booBuddies/effect-94.png new file mode 100644 index 0000000000000000000000000000000000000000..22407492d1af94a359381f54892b9c9fd64c7a94 GIT binary patch literal 503 zcmeAS@N?(olHy`uVBq!ia0vp^3P9Yz!3HF=(z2z16lZ})WHAE+w=f7ZGR&GI0Tfh7 z_6YK2V5m|BDsEF!Z)Q01 zH7f|XZvB|D<8^6OU)*uoy;89fvpTLy3Or7bvzD5Drlu|N-)m=%yHm3-)LHb+)e3sQ z+fKc~z5Jup7Rl=PWmA@%c*^x9Q}7ti7D;W9n`;HFxz-rf*Z=$f_~|MQp{X0HxwYne z4VxdKQCG`rA?_q}Q|4vyy2iqy?!Wqvf9w`NUsayJL)b5`{Jd^J%8Dx8w^|CJ`FYRY zo?*^pyJS}$x51i!$@+y?PI|rHYst#-V9U$^tLoicQ+_dJ{>t@ljLDzzn)7z>gKf18 zb`0_j{0G<{Fn?hD!B7L?3cwgVtlxKQsc%?+;O3kI@1hGzE?wNm+xFAprO=Kh+w>)8 zV_yHi{k~=A<$_bfVSf~g+AeA+N+y|RRqvUmp0TrOuGEd7M=OkXowr#Ksx)2u&irZK zbFc0*wmQJPWN+{F2@EdjC1&~=*JZCiVtu>oanv5HPC3B7;W^Z0A7mM%vey1^nSZ_l P7- 3) then n = 1; end + if(pr <= 0) then pr = 3; end + winding = winding + (v[1]+p.v[n][1])*(v[2]-p.v[n][2]); + + if(p.minX == nil or v[1] < p.minX) then + p.minX = v[1]; + end + if(p.maxX == nil or v[1] > p.maxX) then + p.maxX = v[1]; + end + if(p.minY == nil or v[2] < p.minY) then + p.minY = v[2]; + end + if(p.maxY == nil or v[2] > p.maxY) then + p.maxY = v[2]; + end + end + + --If winding order is anticlockwise, triangulation will fail, so reverse vertex list in that case. + if(winding > 0) then + local pv = p.v[1]; + p.v[1] = p.v[3]; + p.v[3] = pv; + end + + p.Get = function(obj, index) if(index < 1 or index >= 4) then error("Invalid triangle index.", 2); end return { obj.v[index][1]+obj.x, obj.v[index][2]+obj.y }; end - collidersTypeMetatables[TYPE_TRI].__index.Rotate = function(obj, angle) + p.Rotate = function(obj, angle) local s = math.sin(math.pi*angle/180); local c = math.cos(math.pi*angle/180); @@ -322,7 +328,7 @@ do -- Declare Tri methods obj.maxY = t.maxY; end - collidersTypeMetatables[TYPE_TRI].__index.Translate = function(obj, x, y) + p.Translate = function(obj, x, y) for i=1,3 do obj.v[i] = {obj.v[i][1]+x, obj.v[i][2]+y}; end @@ -332,7 +338,7 @@ do -- Declare Tri methods obj.maxY = obj.maxY + y; end - collidersTypeMetatables[TYPE_TRI].__index.Scale = function(obj, x, y) + p.Scale = function(obj, x, y) y = y or x; for i=1,3 do obj.v[i] = {obj.v[i][1]*x, obj.v[i][2]*y}; @@ -343,7 +349,7 @@ do -- Declare Tri methods obj.maxY = obj.maxY*y; end - collidersTypeMetatables[TYPE_TRI].__index.Draw = function(obj, c) + p.Draw = function(obj, c) c = c or 0x00FF0099; Graphics.glSetTextureRGBA(nil, c); local pts = {}; @@ -355,61 +361,25 @@ do -- Declare Tri methods Graphics.glDrawTriangles(pts, {}, 3); Graphics.glSetTextureRGBA(nil, 0xFFFFFFFF); end -end -function colliders.Tri(x,y,p1,p2,p3) - local p = { x=x, y=y, v={p1,p2,p3} }; - - local winding = 0; - for k,v in ipairs(p.v) do - if(v[1] == nil or v[2] == nil) then - error("Invalid polygon definition.", 2); - end - - --Calculate winding order. - local n = k+1; - local pr = k-1; - if(n > 3) then n = 1; end - if(pr <= 0) then pr = 3; end - winding = winding + (v[1]+p.v[n][1])*(v[2]-p.v[n][2]); - - if(p.minX == nil or v[1] < p.minX) then - p.minX = v[1]; - end - if(p.maxX == nil or v[1] > p.maxX) then - p.maxX = v[1]; - end - if(p.minY == nil or v[2] < p.minY) then - p.minY = v[2]; - end - if(p.maxY == nil or v[2] > p.maxY) then - p.maxY = v[2]; - end - end - - --If winding order is anticlockwise, triangulation will fail, so reverse vertex list in that case. - if(winding > 0) then - local pv = p.v[1]; - p.v[1] = p.v[3]; - p.v[3] = pv; - end - setmetatable(p,collidersTypeMetatables[TYPE_TRI]); + setmetatable(p,createMeta(TYPE_TRI)); return p; end -local __typeStringMap = {Player=TYPE_PLAYER, Block=TYPE_BLOCK, Animation=TYPE_ANIM, NPC=TYPE_NPC} local function getType(obj) if(obj.TYPE ~= nil) then return obj.TYPE; + elseif(obj.powerup ~= nil) then + return TYPE_PLAYER; + elseif(obj.slippery ~= nil) then + return TYPE_BLOCK; + elseif(obj.timer ~= nil) then + return TYPE_ANIM; + elseif(obj.id ~= nil) then + return TYPE_NPC; + else + error("Unknown collider type.", 2); end - local t1 = obj.__type - if (t1 ~= nil) then - local t2 = __typeStringMap[t1] - if (t2 ~= nil) then - return t2 - end - end - error("Unknown collider type.", 2); end local function convertPoints(p) @@ -566,48 +536,6 @@ local function testTriPoly(a,b) return false; end -do -- Declare Poly methods - collidersTypeMetatables[TYPE_POLY].__index.Rotate = function(obj, angle) - for k,v in ipairs(obj.tris) do - v:Rotate(angle); - if(v.minX < obj.minX) then obj.minX = v.minX; end - if(v.maxX > obj.maxX) then obj.maxX = v.maxX; end - if(v.minY < obj.minY) then obj.minY = v.minY; end - if(v.maxY > obj.maxY) then obj.maxY = v.maxY; end - end - end - - collidersTypeMetatables[TYPE_POLY].__index.Translate = function(obj, x, y) - for k,v in ipairs(obj.tris) do - v:Translate(x,y); - end - obj.minX = obj.minX + x; - obj.maxX = obj.maxX + x; - obj.minY = obj.minY + y; - obj.maxY = obj.maxY + y; - end - - collidersTypeMetatables[TYPE_POLY].__index.Scale = function(obj, x, y) - y = y or x; - for k,v in ipairs(obj.tris) do - v:Scale(x,y); - end - obj.minX = obj.minX*x; - obj.maxX = obj.maxX*x; - obj.minY = obj.minY*y; - obj.maxY = obj.maxY*y; - end - - collidersTypeMetatables[TYPE_POLY].__index.Draw = function(obj, c) - c = c or 0x0000FF99; - for _,v in ipairs(obj.tris) do - v.x = obj.x; - v.y = obj.y; - Graphics.glSetTextureRGBA(nil, c); - v:Draw(c); - end - end -end function colliders.Poly(x,y,...) local arg = {...}; @@ -706,7 +634,48 @@ function colliders.Poly(x,y,...) p.tris = trilist; - setmetatable(p,collidersTypeMetatables[TYPE_POLY]) + p.Rotate = function(obj, angle) + for k,v in ipairs(obj.tris) do + v:Rotate(angle); + if(v.minX < obj.minX) then obj.minX = v.minX; end + if(v.maxX > obj.maxX) then obj.maxX = v.maxX; end + if(v.minY < obj.minY) then obj.minY = v.minY; end + if(v.maxY > obj.maxY) then obj.maxY = v.maxY; end + end + end + + p.Translate = function(obj, x, y) + for k,v in ipairs(obj.tris) do + v:Translate(x,y); + end + obj.minX = obj.minX + x; + obj.maxX = obj.maxX + x; + obj.minY = obj.minY + y; + obj.maxY = obj.maxY + y; + end + + p.Scale = function(obj, x, y) + y = y or x; + for k,v in ipairs(obj.tris) do + v:Scale(x,y); + end + obj.minX = obj.minX*x; + obj.maxX = obj.maxX*x; + obj.minY = obj.minY*y; + obj.maxY = obj.maxY*y; + end + + p.Draw = function(obj, c) + c = c or 0x0000FF99; + for _,v in ipairs(obj.tris) do + v.x = obj.x; + v.y = obj.y; + Graphics.glSetTextureRGBA(nil, c); + v:Draw(c); + end + end + + setmetatable(p,createMeta(TYPE_POLY)) return p; end @@ -804,27 +773,25 @@ local function testPolyCircle(a,b) return false; end - -local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) +function colliders.linecast(startPoint,endPoint,collider) + + local a,sp,v1 = convertPoints(startPoint); + local b,ep,v2 = convertPoints(endPoint); + local c1n = collider[1] ~= nil; local c0n = collider[0] ~= nil; + if(collider[1] ~= nil) then local hit; local norm; local col; - for _,v in pairs(collider) do - local bl,pt,nm,_,sqrDist = linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,v,maxSqrDist); - if(bl) then - if (sqrDist == nil) then - sqrDist = (pt-v1).sqrlength; - end - if(sqrDist < maxSqrDist) then - maxSqrDist = sqrDist; - hit = pt; - norm = nm; - col = v; - end + for _,v in pairs(collider) do + local bl,pt,nm = colliders.linecast(startPoint,endPoint,v); + if(bl and (hit == nil or (pt-v1).sqrlength < (hit-v1).sqrlength)) then + hit = pt; + norm = nm; + col = v; end end if(hit ~= nil) then @@ -836,7 +803,7 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) local c = colliders.getHitbox(collider); - + local aabb = colliders.Box(math.min(v1.x,v2.x),math.min(v1.y,v2.y),math.abs(v2.x-v1.x),math.abs(v2.y-v1.y)); local cbb = colliders.getAABB(collider); if(not colliders.collide(aabb,cbb)) then @@ -846,7 +813,7 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) if(sp.x == ep.x and sp.y == ep.y) then local b = colliders.collide(sp,c); if(b) then - return true, v1, vect.zero2, collider; + return true, vect.v2(sp), vect.zero2, collider; else return false, nil, nil, nil; end @@ -864,68 +831,41 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) or intersect(a,b,{c.x+c.width,c.y},{c.x+c.width,c.y+c.height}) or intersect(a,b,{c.x+c.width,c.y+c.height},{c.x,c.y+c.height}) or intersect(a,b,{c.x,c.y+c.height},{c.x,c.y}));--]] - - local hit,nm,col,p; - local top = c.y - local right = c.x + c.width - local bottom = c.y + c.height - local left = c.x - if (dy > 0) and ((top - a[2])*(top - a[2]) < maxSqrDist) then - col,p = intersectpoint(a,b,{left,top},{right,top}); -- Top - if(col) then - local sqrDist = (p-v1).sqrlength - if (hit == nil) or (sqrDist < maxSqrDist) then - maxSqrDist = sqrDist; - hit = p; - nm = -vect.up2; - end - end + local hit,nm; + local col,p = intersectpoint(a,b,{c.x,c.y},{c.x+c.width,c.y}); + if(col) then + hit = p; + nm = -vect.up2; end - if (dx < 0) and ((right - a[1])*(right - a[1]) < maxSqrDist) then - col,p = intersectpoint(a,b,{right,top},{right,bottom}) -- Right - if(col) then - local sqrDist = (p-v1).sqrlength - if (hit == nil) or (sqrDist < maxSqrDist) then - maxSqrDist = sqrDist; - hit = p; - nm = vect.right2; - end - end + col,p = intersectpoint(a,b,{c.x+c.width,c.y},{c.x+c.width,c.y+c.height}) + if(col and (hit == nil or (p-v1).sqrlength < (hit-v1).sqrlength)) then + hit = p; + nm = vect.right2; end - if (dy < 0) and ((bottom - a[2])*(bottom - a[2]) < maxSqrDist) then - col,p = intersectpoint(a,b,{left,bottom},{right,bottom}) -- Bottom - if(col) then - local sqrDist = (p-v1).sqrlength - if (hit == nil) or (sqrDist < maxSqrDist) then - maxSqrDist = sqrDist; - hit = p; - nm = vect.up2; - end - end + col,p = intersectpoint(a,b,{c.x+c.width,c.y+c.height},{c.x,c.y+c.height}) + if(col and (hit == nil or (p-v1).sqrlength < (hit-v1).sqrlength)) then + hit = p; + nm = vect.up2; end - if (dx > 0) and ((left - a[1])*(left - a[1]) < maxSqrDist) then - col,p = intersectpoint(a,b,{left,top},{left,bottom}) -- Left - if(col) then - local sqrDist = (p-v1).sqrlength - if (hit == nil) or (sqrDist < maxSqrDist) then - maxSqrDist = sqrDist; - hit = p; - nm = -vect.right2; - end - end + col,p = intersectpoint(a,b,{c.x,c.y+c.height},{c.x,c.y}) + if(col and (hit == nil or (p-v1).sqrlength < (hit-v1).sqrlength)) then + hit = p; + nm = -vect.right2; end if(hit ~= nil) then - return true, hit, nm, collider, maxSqrDist; + return true, hit, nm, collider; else - return false, nil, nil, nil, nil; + return false, nil, nil, nil; end elseif(t == TYPE_CIRCLE) then local centre = vect.v2(c.x,c.y); local t1 = v1-centre; local t2 = v2-centre; - local drsqr = dx*dx + dy*dy; + local dx = t2.x-t1.x; + local dy = t2.y-t1.y; + local dr = math.sqrt(dx*dx + dy*dy); local D = t1.x*t2.y - t2.x*t1.y; - local delta = c.radius*c.radius*drsqr - D*D; + local delta = c.radius*c.radius*dr*dr - D*D; if(delta < 0) then return false, nil, nil, nil; else @@ -933,10 +873,10 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) if(dy < 0) then sdy=-1; else sdy = 1; end local qx = sdy*dx*math.sqrt(delta); local qy = math.abs(dy)*math.sqrt(delta); - local px1 = (D*dy + qx)/drsqr; - local px2 = (D*dy - qx)/drsqr; - local py1 = (-D*dx + qy)/drsqr; - local py2 = (-D*dx - qy)/drsqr; + local px1 = (D*dy + qx)/(dr*dr); + local px2 = (D*dy - qx)/(dr*dr); + local py1 = (-D*dx + qy)/(dr*dr); + local py2 = (-D*dx - qy)/(dr*dr); local p1 = vect.v2(px1,py1); local p2 = vect.v2(px2,py2); if((p2-t1).sqrlength < (p1-t1).sqrlength) then @@ -980,13 +920,13 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) end return false;]] local bb = colliders.Box(c.minX+c.x, c.minY+c.y, c.maxX-c.minX, c.maxY-c.minY); - if(not linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,bb,maxSqrDist)) then return false,nil,nil,nil; end + if(not colliders.linecast(startPoint, endPoint, bb)) then return false,nil,nil,nil; end local hit; local norm; for k,v in ipairs(c.tris) do - local ht,pt,nm = linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,v,maxSqrDist); + local ht,pt,nm = colliders.linecast(startPoint,endPoint,v); if(ht and (hit == nil or (pt-v1).sqrlength < (hit-v1).sqrlength)) then hit = pt; norm = nm; @@ -1001,7 +941,7 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) elseif(t == TYPE_TRI) then local bb = colliders.Box(c.minX+c.x, c.minY+c.y, c.maxX-c.minX, c.maxY-c.minY); - if(not linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,bb,maxSqrDist)) then return false,nil,nil,nil; end + if(not colliders.linecast(startPoint, endPoint, bb)) then return false,nil,nil,nil; end local hit; local dir; @@ -1026,63 +966,57 @@ local function linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,maxSqrDist) end end -function colliders.linecast(startPoint,endPoint,collider) - local a,sp,v1 = convertPoints(startPoint); - local b,ep,v2 = convertPoints(endPoint); - local aabb = colliders.Box(math.min(v1.x,v2.x),math.min(v1.y,v2.y),math.abs(v2.x-v1.x),math.abs(v2.y-v1.y)); - local dx = b[1] - a[1]; - local dy = b[2] - a[2]; - return linecast_internal(a,sp,v1,b,ep,v2,dx,dy,aabb,collider,dx*dx+dy*dy); -end - function colliders.raycast(startPoint,direction,collider) local _,_,sp = convertPoints(startPoint); local _,_,dir = convertPoints(direction); return colliders.linecast(sp,sp-dir,collider); end --- /| --- /_| ---Slope bottomleft to topright floor -local getBlockHitbox_lrslope_floor = {452,321,365,316,357,358,306,305,302,616,299,340,341,472,480,636,635,326,324,604,600,332}; - --- |\ --- |_\ ---Slope topleft to bottomright floor -local getBlockHitbox_rlslope_floor = {451,319,366,315,359,360,308,307,301,617,300,343,342,474,482,638,637,327,325,601,605,333}; - --- |-/ --- |/ ---Slope bottomleft to topright ceil -local getBlockHitbox_lrslope_ceil = {318,367,363,364,314,313,310,479,485,328,614,613,334}; - --- \-| --- \| ---Slope topleft to bottomright ceil -local getBlockHitbox_rlslope_ceil = {317,368,361,362,312,311,309,476,486,329,77,78,335}; - --- [][] --- ---Vertical half block -local getBlockHitbox_uphalf = {289,168,69}; - --- Create mappings for fast access -local getBlockHitbox_lrslope_floor_map = MakeBlockIdTestMap(getBlockHitbox_lrslope_floor) -local getBlockHitbox_rlslope_floor_map = MakeBlockIdTestMap(getBlockHitbox_rlslope_floor) -local getBlockHitbox_lrslope_ceil_map = MakeBlockIdTestMap(getBlockHitbox_lrslope_ceil) -local getBlockHitbox_rlslope_ceil_map = MakeBlockIdTestMap(getBlockHitbox_rlslope_ceil) -local getBlockHitbox_uphalf_map = MakeBlockIdTestMap(getBlockHitbox_uphalf) - local function getBlockHitbox(id, x, y, wid, hei) - if getBlockHitbox_lrslope_floor_map[id] then --Slope bottomleft to topright floor + + -- /| + -- /_| + --Slope bottomleft to topright floor + local lrslope_floor = {452,321,365,316,357,358,306,305,302,616,299,340,341,472,480,636,635,326,324,604,600,332}; + + -- |\ + -- |_\ + --Slope topleft to bottomright floor + local rlslope_floor = {451,319,366,315,359,360,308,307,301,617,300,343,342,474,482,638,637,327,325,601,605,333}; + + -- |-/ + -- |/ + --Slope bottomleft to topright ceil + local lrslope_ceil = {318,367,363,364,314,313,310,479,485,328,614,613,334}; + + -- \-| + -- \| + --Slope topleft to bottomright ceil + local rlslope_ceil = {317,368,361,362,312,311,309,476,486,329,77,78,335}; + + -- [][] + -- + --Vertical half block + local uphalf = {289,168,69}; + + local isAny = function(tbl, val) + for _,v in ipairs(tbl) do + if v == val then + return true; + end + end + return false; + end + + if isAny(lrslope_floor,id) then --Slope bottomleft to topright floor return colliders.Tri(x,y,{0,hei},{wid,0},{wid,hei}); - elseif getBlockHitbox_rlslope_floor_map[id] then --Slope topleft to bottomright floor + elseif isAny(rlslope_floor,id) then --Slope topleft to bottomright floor return colliders.Tri(x,y,{0,0},{wid,hei},{0,hei}); - elseif getBlockHitbox_lrslope_ceil_map[id] then --Slope bottomleft to topright ceil + elseif isAny(lrslope_ceil,id) then --Slope bottomleft to topright ceil return colliders.Tri(x,y,{0,0},{wid,0},{0,hei}); - elseif getBlockHitbox_rlslope_ceil_map[id] then --Slope topleft to bottomright ceil + elseif isAny(rlslope_ceil,id) then --Slope topleft to bottomright ceil return colliders.Tri(x,y,{0,0},{wid,0},{wid,hei}); - elseif getBlockHitbox_uphalf_map[id] then --Vertical half block + elseif isAny(uphalf,id) then --Vertical half block return colliders.Box(x,y,wid,hei/2); else return colliders.Box(x,y,wid,hei); @@ -1090,11 +1024,12 @@ local function getBlockHitbox(id, x, y, wid, hei) end function colliders.getAABB(a) + local ta = getType(a); + + if(a.TYPE == TYPE_BOX) then return a; end - - local ta = getType(a); if(ta == TYPE_BLOCK or ta == TYPE_PLAYER or ta == TYPE_NPC or ta == TYPE_ANIM) then return colliders.getHitbox(a); @@ -1108,12 +1043,12 @@ function colliders.getAABB(a) end function colliders.getHitbox(a) + local ta = getType(a); + if(a.TYPE ~= nil) then return a; end - local ta = getType(a); - if(ta == TYPE_BLOCK) then return getBlockHitbox(a.id, a.x, a.y, a.width, a.height); elseif(ta == TYPE_PLAYER) then diff --git a/LuaScriptsLibExt/deathTracker.lua b/LuaScriptsLibExt/deathTracker.lua new file mode 100644 index 000000000..b1d7523aa --- /dev/null +++ b/LuaScriptsLibExt/deathTracker.lua @@ -0,0 +1,102 @@ +--[[ +·▄▄▄▄ ▄▄▄ . ▄▄▄· ▄▄▄▄▄ ▄ .▄▄▄▄▄▄▄▄▄ ▄▄▄· ▄▄· ▄ •▄ ▄▄▄ .▄▄▄ ▄▄▌ ▄• ▄▌ ▄▄▄· +██▪ ██ ▀▄.▀·▐█ ▀█ •██ ██▪▐█•██ ▀▄ █·▐█ ▀█ ▐█ ▌▪█▌▄▌▪▀▄.▀·▀▄ █· ██• █▪██▌▐█ ▀█ +▐█· ▐█▌▐▀▀▪▄▄█▀▀█ ▐█.▪██▀▐█ ▐█.▪▐▀▀▄ ▄█▀▀█ ██ ▄▄▐▀▀▄·▐▀▀▪▄▐▀▀▄ ██▪ █▌▐█▌▄█▀▀█ +██. ██ ▐█▄▄▌▐█ ▪▐▌ ▐█▌·██▌▐▀ ▐█▌·▐█•█▌▐█ ▪▐▌▐███▌▐█.█▌▐█▄▄▌▐█•█▌ ▐█▌▐▌▐█▄█▌▐█ ▪▐▌ +▀▀▀▀▀• ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀ · ▀▀▀ .▀ ▀ ▀ ▀ ·▀▀▀ ·▀ ▀ ▀▀▀ .▀ ▀ ▀ .▀▀▀ ▀▀▀ ▀ ▀ +--V. 1.0 +--written by Enjl +]] +local lvlDeath = Data(Data.DATA_LEVEL, "deathTracker", true) + +local lastPlayerX = 0 +local lastPlayerY = 0 +local deathCounter = 0 + +local hasDied = false + +local deathTracker = {} + +local shownIcons = {} + +deathTracker.ICON_STANDARD = Graphics.loadImage(Misc.resolveFile("deathTracker\\deathIcon.png")) +deathTracker.ICON_STANDARD2X = Graphics.loadImage(Misc.resolveFile("deathTracker\\deathIcon2x.png")) +deathTracker.ICON_ARROW = Graphics.loadImage(Misc.resolveFile("deathTracker\\arrowIcon.png")) +deathTracker.ICON_ARROW2X = Graphics.loadImage(Misc.resolveFile("deathTracker\\arrowIcon2x.png")) +deathTracker.ICON_PLAYER1 = Graphics.loadImage(Misc.resolveFile("deathTracker\\player1.png")) +deathTracker.ICON_PLAYER2 = Graphics.loadImage(Misc.resolveFile("deathTracker\\player2.png")) +deathTracker.ICON_PLAYER3 = Graphics.loadImage(Misc.resolveFile("deathTracker\\player3.png")) +deathTracker.ICON_PLAYER4 = Graphics.loadImage(Misc.resolveFile("deathTracker\\player4.png")) +deathTracker.ICON_PLAYER5 = Graphics.loadImage(Misc.resolveFile("deathTracker\\player5.png")) +deathTracker.ICON_TRUMP = Graphics.loadImage(Misc.resolveFile("deathTracker\\trump.png")) +deathTracker.ICON_SWEAT = Graphics.loadImage(Misc.resolveFile("deathTracker\\sweat smile.png")) +deathTracker.ICON_CAT = Graphics.loadImage(Misc.resolveFile("deathTracker\\cat.png")) + +deathTracker.iconSprite = deathTracker.ICON_STANDARD2X + +local function iconHandler() + for i=1, deathCounter do + local entry = {} + entry.x = tonumber(lvlDeath:get("deathX" .. tostring(i))) + entry.y = tonumber(lvlDeath:get("deathY" .. tostring(i))) + entry.timer = 0 + entry.opacity = 0 + entry.sprite = deathTracker.iconSprite + table.insert(shownIcons, entry) + end +end + +function deathTracker.onInitAPI() + registerEvent(deathTracker, "onTick", "onTick", false) + registerEvent(deathTracker, "onDraw", "onDraw", false) + registerEvent(deathTracker, "onStart", "onStart", false) +end + +function deathTracker.onStart() + if lvlDeath:get("deaths") == nil then + lvlDeath:set("deaths", 0) + lvlDeath:save() + end + deathCounter = tonumber(lvlDeath:get("deaths")) or 0 +end + +function deathTracker.onDraw() + local cam = Camera.get()[1] + for k,v in ipairs(shownIcons) do + if v.x + 0.5 * v.sprite.width > cam.x and v.x -0.5 * v.sprite.width < cam.x + 800 and v.y + 0.5 * v.sprite.height > cam.y and v.y -0.5 * v.sprite.height < cam.y + 600 then + Graphics.drawImageToScene(v.sprite, v.x - 0.5 * v.sprite.width, v.y - v.sprite.height, v.opacity) + end + end +end + +function deathTracker.onTick() + local cam = Camera.get()[1] + --track player position for onscreen depiction of offscreen deaths + if player.x + player.width > cam.x and player.x < cam.x + 800 then + lastPlayerX = player.x + 0.5 * player.width + end + if player.y + player.height > cam.y and player.y < cam.y + 600 then + lastPlayerY = player.y + 0.5 * player.height + end + --add to counter + if player:mem(0x13E, FIELD_WORD) > 0 then + if hasDied == false then + hasDied = true + deathCounter = deathCounter + 1 + lvlDeath:set("deaths", tostring(deathCounter)) + lvlDeath:set("deathX" .. tostring(deathCounter), tostring(lastPlayerX)) + lvlDeath:set("deathY" .. tostring(deathCounter), tostring(lastPlayerY)) + lvlDeath:save() + iconHandler() + end + for k,v in ipairs(shownIcons) do + v.timer = v.timer + 1 + if v.timer > 50 then + v.opacity = v.opacity + 0.1 + end + end + end +end + +return deathTracker; +--cat planet cat planet \ No newline at end of file diff --git a/LuaScriptsLibExt/deathTracker/arrowIcon.png b/LuaScriptsLibExt/deathTracker/arrowIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..21c3cc3aa5bd122bce7d94f1bb4dac3b02840412 GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NS%G}c0*}aI z1_r)^Ak4U9V)k30phSslL`iUdT1k0gQ7S`0VrE{6US4X6f{C7io@I`4ogV`OBcG>> zV@QPi+ev|ZhYdKKt7pj--M78>ZVIcEz`{JIm-j`Mn5*`6|J}HD%A`ene>MKua*3pG zIgqzWb%BM`;qQBw`z>P;algTIze+8vF*HFmf;Fu1zlMXn@{_y2DwNS%G}c0*}aI z1_r)^Ak4U9V)k30phSslL`iUdT1k0gQ7S`0VrE{6US4X6f{C7io@I`4ogYxmB~KT} zkO=p;Q@r^OEAX&d`tsc@eK+^ogM|rBt2AnMB`n!~z${HH@D4NIj=|H_&t;ucLK6UpYl9B} literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/cat.png b/LuaScriptsLibExt/deathTracker/cat.png new file mode 100644 index 0000000000000000000000000000000000000000..74426b5544c42353990777b72af225763e123fd5 GIT binary patch literal 1398 zcmV-+1&R8JP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y1m{UaK~zXfy_J1TlUEeRZwpufg|-wbw4Li0BM+(RFIjOl3};PEcg{fe0uS zht5p>Yc3KNr9j_4JGXreGd25jPjd6#_nhbX_1v4ZW&exj#xUdJsnWc(IA)+%FL(7n z<;A@`!?R+|Q%h%fuit4=Vo$!};ifFV()4&Xipmmq_a#Yqk9)Y6XLwfZd1}KF-)%pZ zX;J_6aGWU7fCBf{rODP9g4qz!!uZ}yHQwVM?&TSt6)m3HlI>S|u0oHNLy@Sh9FFg| zgkif`-dnKPcfWao?>xTpXusX8=smnegW5eKTwb2xSrOwYezX&%I-D*a0c(*47bow-zBPE*f=qiG7dY9q13JmeYAiWpC2&XlH~DjU{ozcLX* zYYJV%QrE=7y#iW=v^LPYdtygxDjamGo(3aMmIU`^CQ8#qjE8(I3uM-tbZ?I9F%WJh z!FhWDggeU#ww@-nxIV;jXC;K&3n8>5lW#H{SH|MTfiPIoy{(+#M*T|$9UE4>+TZs0 z)NnYjM?+{!z|+?0uy>>pJd>u(cAua<9rpHQJZ+v#AO04EE2HtKMu*}L{cM~e;s%uR zHjCR|7}(u)UJo=G@t|%DmS#j_@3skWb|lf!=}zf-oVEn)EiqDWJRa0W0M|z1={X&~ z*%;W(86s{#i>66GswoLV&qV^?j6ijT8U|xLW>0?|T{jFgT_Oa!)2^#}%u3X`deysB zK(ijt>vVL_LEsD#H=q@>y>``AgrM)T4tspOomS4Mz8`F?e)sGag+nM0dRr&(16H7xkJBs&JIRd-ME}zi7{(LBk zvIZeFR?<0I&1P#E^A)j-nF5*I6v|Sgv~1IRlO(_ArujH`=M2T^Qu@uHulJKnktnmM zP?n>>pLKe)AJX9r^>*h3z%t**nKDuGaNKKb^SCgU9yN>wi&&ai$pXe}*>q~I923eG z&78n;mM2TBIq&!WE*1NQiRIyOr6FppBQQ^!m zKAg>Z2|O~04K*p5hPJQz8+suQc>#K*=)__CS{Y;PAES`Bx|5bn2LJ#707*qoM6N<$ Ef|<{b(f|Me literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/deathIcon.png b/LuaScriptsLibExt/deathTracker/deathIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..19a98bad8b03370514187c579f1b68f660f018aa GIT binary patch literal 499 zcmVN2bZe?^J zG%heMIczh2P5=M_aY;l$R9HvFlwpnnAq<7RuxIoj8_zL6Sze_G{WxUt}>faVPX7CQWRjNwW?qcdbT5CQ!WvIfRq?p0>B6_WYV z4hrPkbwPL&ku!%;U^Zj}SWl+wS?r4o*zm>TP;ahx0#(9k4uva$ehnW5$Ut2b30F$L z%#t%IAPN2bZe?^J zG%heMIczh2P5=M_F-b&0R9HvVm9Y)NFcd^H37($gWa0woiqKy)m@Ds*f?#||k! z{y)CRzBnEM9g`I;NQI2S^Ny^x3Kld?Gb=$c%h5nq z*#bksZX$y3nVdf;602kZ`$*Wx$n_dA^`1fQ{}ccm#H40Y{BHr^HjI93IhI#Io=-`^ zgB;BC{E3~)0t-AIVkFGUYrSsSY>eK$KZlR+JABTf3fP~+{dNfxfe&+hj~wJK zq5u>>1w)Inq;@!vqk*jA1t2q=cRMjoC!<@E3JdW*%wZ4qYCulK3k=B?3>NX{@ae$Z zDqf)dxgL+AbVWQkhffFQR`CK*`xKXpgy38a-&XMg?NjXc5`uFzd|Sl}m=3GeJ;WdX dPV*F~syE_PA5jhayw(5!002ovPDHLkV1kS9taShY literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/player1.png b/LuaScriptsLibExt/deathTracker/player1.png new file mode 100644 index 0000000000000000000000000000000000000000..2523f35c267790ea7834c8f0c12e550c48b9b1ea GIT binary patch literal 490 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y0b5B#K~z{r)s(Su!!Qs8QHDc@3>B&bhYA(C z1ec%^T!KT5D{u)a!=Xck$Y=q>#gONJ5(+GW!3H?|-QREq41M3);#ub-%bG?-Q;S>VB3@eMiXx^HqwF!=BS44e-kbG_^`=mhet^aq1p77sph$VG3z04x=$T@2iB zr@;4Vm*GCfm|-EHGlx&}xZiGp@~k|Dx$PAI1~B|7P>B{m*L{;ig2B}az&Ok@E>Y_@ g#YAm@N1eY9zcZ`-YKO~m4FCWD07*qoM6N<$g3AocssI20 literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/player2.png b/LuaScriptsLibExt/deathTracker/player2.png new file mode 100644 index 0000000000000000000000000000000000000000..0162005fee52698fe9ebc96b897109894e6761d3 GIT binary patch literal 465 zcmV;?0WSWDP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y0YXVcK~z{r-ISqm#4r#=RgU46a?mhk1iFMP zAutmZm=aRL!N9(@1}IPY&_P0T1lg?%zKiOJP}-O$@{E_7^M<3sbbPmfXYg zurS3E4982Tcz&if)@TsVNA<@CK$t(K#O*RB%I3)T(>bBF zr&9yI>_P7*01beSq3UI?rE8F~H-g?z03A?W4fvFx=Pf_##|O}B!gZo<8MV%-)i+1~J3(5D@xd3p{{YYm;_12=I6qE+uj!QFe4gh-UbvF=wU0UVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y0hUQbK~z{r)s`_*!$1s0a|BA4IYy3=G9^dI zQG5hSCKV-RN=iyfj^WOrW#7*FN17~5Vw>U>`jY4Wj$;$UFq{mpXI$$muIRB? z@U3yhIdDbex2IFC?Yp9}STOX5&B?&%{kTm;HS?ZVjVspNJ-FX}FVtiM7|y#y2?}c6 zQ{Ux-5jd5e?5+PBp>Nig3%)pY4&-#jDC?h(heT8}e{uTkUrxPzuna_jUDqXs=VO98 zdH{at>kGz^1q{)t745T+zP@01+3rt96b!EqT|#vY#!qu5g)w_D1H-c-i9k0o{4d{ zU>3@Wh1#^nn>FZb&ZIC}jTCRzpszV`ASabmUi5Qa`qhrt{|CXcSo%V1e?7s#0Pxoa z(A6-S1I?KfhAu>gHxC93_#{S#5Y2nuhASG8kr!%2^PaciiUx}iJs|3X=WV#6p$4-B nL#t8i9Jpdlt6}Th598(w`eB`hkN@X&ZA72k^N3=g_>I$=bibDD_myNg%tDb^5zYY^(No?r}77 z+a>?ux4h!q{vS<=(OPl|awn}D8*-M<`K)6XFV|+dBDPgTRLf;ynP`y7jStnEHJ?28 zYqEQv_Z?D*{f25uvtJm)G ztmkt)6VI3?MSY(0SiVe?mu;WKhvH{eJ<4F?<$rz9R!9&Nu>nRAgQu&X%Q~loCIE9h*B<}? literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/player5.png b/LuaScriptsLibExt/deathTracker/player5.png new file mode 100644 index 0000000000000000000000000000000000000000..164371c8c1ae94e808f147597675868983e2947b GIT binary patch literal 659 zcmV;E0&M+>P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9 za%BK;VQFr3E^cLXAT%y8E;(#7eog=Y0t87!K~z{r)t9kt!!Q&?HHy1T;?iZtNa+>4 zLdvv8x~z~HQl?GoR;2<8cmj34FUm43%EbftKl$&@req{d*L63s+wDH*;AS1RIfXNG zxLJp7IuL$4HzVGEJb9Re(@fZ=1EJLes1O`ZO%HV`80S=fR5%z^Rto?KsB!ys?4i~m z5Cyq1ieRvM0Qh^|_sk6doJ04@D1t#)EdT=w0jRke<@o~ugBV{Wc|0{w_#!9c{r z0&uWI6d=NxIkq1F!w7j9RZ`*be%-0XVqVxkp5TL&lKKOP5@DOSc$cGbLg+7!B&!v6<76=do z=tqY41{oF%Ru7=)!&eGIotsQCEErT)3lM>z1^^8LPRn7NIS5t@00nJ%ILseW&TL z%|v7r^?`k->9Ea&8mTb#y;otI2?QcR>W2k@NQk}~E1Uz>85NFbkiIj`;T)*Ws8|BR tk)fjVqhbjNR}T;wl(5ZPxGzB0`~ylinIcU|zc&B?002ovPDHLkV1kuK1^@s6 literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/deathTracker/sweat smile.png b/LuaScriptsLibExt/deathTracker/sweat smile.png new file mode 100644 index 0000000000000000000000000000000000000000..b8848b2b756e462e0f8933b8c52261cb9011fad8 GIT binary patch literal 1351 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 VhN)xkyN3V(002ovPDHLkV1j%Z>*)Xh literal 0 HcmV?d00001 diff --git a/LuaScriptsLibExt/debug.lua b/LuaScriptsLibExt/debug.lua new file mode 100644 index 000000000..61a8635c7 --- /dev/null +++ b/LuaScriptsLibExt/debug.lua @@ -0,0 +1,68 @@ +--debug.lua +--By PixelPest +--1.2 + + +local debug = {}; +local debugTable = {}; + + +function debug.onInitAPI() + registerEvent(debug, "onTickEnd", "onTickEnd", false); +end + + +function debug.type(obj, heading) + local h = heading or ""; + table.insert(debugTable, {h, type(obj)}); +end + + +function debug.simple(obj, heading) + local h = heading or ""; + + if (type(obj) ~= "string") and (type(obj) ~= "number") and (type(obj) ~= "boolean") and (type(obj) ~= "nil") then + error("Variable defined by "..h.." is not considered simple (string nor boolean nor number nor nil)."); + end + + table.insert(debugTable, {h, obj}); +end + +function debug.table(obj, heading) + local h = heading or ""; + + if obj == nil then + table.insert(debugTable, {h, "nil"}); + elseif type(obj) ~= "table" then + error("Variable defined by "..h.." is not a table."); + else + for k, v in pairs(obj) do + table.insert(debugTable, {h.."["..k.."]", v}) + end + end +end + +function debug.onTickEnd() + if #debugTable > 30 then + error("Too many lines (>30)."); + end + + local yCounter = 0; + + for _, v in pairs(debugTable) do + if v[1] == "" then + Text.printWP(tostring(v[2]), 0, yCounter, 10); + else + Text.printWP(v[1]..": "..tostring(v[2]), 0, yCounter, 10); + end + + yCounter = yCounter + 20; + end + + debugTable = {}; +end + + +return debug + + diff --git a/LuaScriptsLibExt/eventu.lua b/LuaScriptsLibExt/eventu.lua index fd65b9a8e..0dbd21259 100644 --- a/LuaScriptsLibExt/eventu.lua +++ b/LuaScriptsLibExt/eventu.lua @@ -1,6 +1,20 @@ ---eventu.lua ---v1.0.4 ---Created by Hoeloe, 2015 +----------------------------------------- +----------------------------------------- +--*************************************-- +--* ______ _ _ _ *-- +--* | ____| | | | | | | *-- +--* | |____ _____ _ __ | |_| | | | *-- +--* | __\ \ / / _ \ '_ \| __| | | | *-- +--* | |___\ V / __/ | | | |_| |__| | *-- +--* |______\_/ \___|_| |_|\__|\____/ *-- +--* *-- +--*************************************-- +----------------------------------------- +----------------------------------------- +--------Created by Hoeloe - 2015--------- +------Open-Source Coroutine Library------ +---------For Super Mario Bros X---------- +-----------------v1.1.0------------------ local eventu = {} local secondsQueue = {} @@ -163,6 +177,7 @@ function eventu.waitEvent(name) end function eventu.signal(name) + if(signalQueue[name] == nil) then return end; local waketable = {} for k,v in pairs(signalQueue[name]) do signalQueue[name][k] = nil; @@ -175,9 +190,12 @@ function eventu.signal(name) end end -function eventu.setTimer(secs, func, repeated) - repeated = repeated or false; - local _,c = eventu.run(function() +function eventu.setTimer(secs, func, repeated) + local f; + if(repeated == nil or type(repeated) ~= "number") then + repeated = repeated or false; + + f = function() repeat eventu.waitSeconds(secs); func(); @@ -187,13 +205,30 @@ function eventu.setTimer(secs, func, repeated) repeated = false; end until repeated == false; - end); + end + else + f = function() + for i=1,repeated do + eventu.waitSeconds(secs); + func(i); + local co = getCurrentCoroutine(); + if(breakQueue[co] == true) then + breakQueue[co] = nil; + break; + end + end + end + end + local _,c = eventu.run(f); return c; end function eventu.setFrameTimer(frames, func, repeated) - repeated = repeated or false; - local _,c = eventu.run(function() + local f; + if(repeated == nil or type(repeated) ~= "number") then + repeated = repeated or false; + + f = function() repeat eventu.waitFrames(frames); func(); @@ -203,7 +238,22 @@ function eventu.setFrameTimer(frames, func, repeated) repeated = false; end until repeated == false; - end); + end + + else + f = function() + for i = 1,repeated do + eventu.waitFrames(frames); + func(i); + local co = getCurrentCoroutine(); + if(breakQueue[co] == true) then + breakQueue[co] = nil; + break; + end + end + end + end + local _,c = eventu.run(f); return c; end @@ -230,9 +280,34 @@ function eventu.breakTimer() breakQueue[co] = true; end +function eventu.abort(co) + if(co ~= nil) then + secondsQueue[co] = nil; + framesQueue[co] = nil; + inputQueue[co] = nil; + for k,v in pairs(signalQueue) do + for l,w in ipairs(v) do + if(w == co) then + table.remove(v,l); + break; + end + end + end + for k,v in pairs(eventQueue) do + for l,w in ipairs(v) do + if(w == co) then + table.remove(v,l); + break; + end + end + end + pausedQueue[co] = nil; + end +end + function eventu.registerKeyEvent(key, func, consume) consume = consume or false; - eventu.run(function() + local _,c = eventu.run(function() repeat eventu.waitForInput(key); func(); @@ -243,11 +318,12 @@ function eventu.registerKeyEvent(key, func, consume) end until consume == true; end); + return c; end function eventu.registerSMBXEvent(event, func, repeated) repeated = repeated or false; - eventu.run(function() + local _,c = eventu.run(function() repeat eventu.waitEvent(event); func(); @@ -258,6 +334,7 @@ function eventu.registerSMBXEvent(event, func, repeated) end until repeated == false; end); + return c; end return eventu; \ No newline at end of file diff --git a/LuaScriptsLibExt/metaluna.lua b/LuaScriptsLibExt/metaluna.lua new file mode 100644 index 000000000..4e58a2e5e --- /dev/null +++ b/LuaScriptsLibExt/metaluna.lua @@ -0,0 +1,84 @@ +--***************** +--* metaluna.lua * +--* v1.0 * +--* * +--***************** + +local metaluna = {} +local sectionIds = {} + + +if Animation.__tostring == nil then +function Animation.__tostring(obj) + return "Animation (id="..obj.id..", x="..obj.x..", y="..obj.y..")" +end; end; + +if BGO.__tostring == nil then +function BGO.__tostring(obj) + return "BGO (id="..obj.id..", x="..obj.x..", y="..obj.y..")" +end; end; + +if Block.__tostring == nil then +function Block.__tostring(obj) + return "Block (id="..obj.id..", x="..obj.x..", y="..obj.y..")" +end; end; + +if Camera.__tostring == nil then +function Camera.__tostring(obj) + return "Camera (x="..obj.x..", y="..obj.y..", w="..obj.width..", h="..obj.height..")" +end; end; + +if Layer.__tostring == nil then +function Layer.__tostring(obj) + return "Layer ("..obj.layerName..")" +end; end; + +if Level.__tostring == nil then +function Level.__tostring(obj) + return "Level (title="..obj.title..")" +end; end; + +if NPC.__tostring == nil then +function NPC.__tostring(obj) + return "NPC (id="..obj.id..")" +end; end; + +if Player.__tostring == nil then +function Player.__tostring(obj) + return "Player (char="..obj.character..")" +end; end; + +if RECT.__tostring == nil then +function RECT.__tostring(obj) + return "RECT (l="..tostring(obj.left)..",r="..tostring(obj.right)..",".."t="..tostring(obj.top)..",b="..tostring(obj.bottom)..")" +end; end; + +if RECTd.__tostring == nil then +function RECTd.__tostring(obj) + return "RECTd (l="..tostring(obj.left)..",r="..tostring(obj.right)..",".."t="..tostring(obj.top)..",b="..tostring(obj.bottom)..")" +end; end; + +if Section.__tonumber == nil then +function Section.__tonumber(obj) + local secId = 1 + for k,v in pairs (Section.get()) do + if v == obj then + secId = k + break; + end + end + + return secId +end; end; + +if Section.__tostring == nil then +function Section.__tostring(obj) + return "Section ("..tostring(tonumber(obj))..")" +end; end; + +if Warp.__tostring == nil then +function Warp.__tostring(obj) + return "Warp ("..tostring(obj:mem (0x5A, FIELD_WORD))..")" +end; end; + +return metaluna; \ No newline at end of file diff --git a/LuaScriptsLibExt/npcParse.lua b/LuaScriptsLibExt/npcParse.lua new file mode 100644 index 000000000..3f1bf1d82 --- /dev/null +++ b/LuaScriptsLibExt/npcParse.lua @@ -0,0 +1,278 @@ +-- npcParse.lua +-- v1.2 + +local lunajson = API.load("ext/lunajson") +local pnpc = API.load("pnpc") +local npcParse = {} + +local textblox +local textbloxActive = false + +if pcall(function() textblox = API.load("textblox") end) then + textbloxActive = true; +end + + + +npcParse.debug = false + + + +npcParse.externalJson = {} +npcParse.idGroups = {} + + +local areAllLoaded = false +npcParse.active = true +npcParse.clearAfter = true +local useLoadstring = true + + +function npcParse.onInitAPI () + registerEvent(npcParse, "onStart", "onStartStart", true) + registerEvent(npcParse, "onStart", "onStartEnd", false) + registerEvent(npcParse, "onTick", "onTickStart", true) + registerEvent(npcParse, "onTick", "onTickEnd", false) + registerEvent(npcParse, "onCameraUpdate", "onCameraUpdate", false) +end + + +-- This function loads the data from the npcdata.json file +local function loadExternalJson () + -- Get the full file path + local p = Misc.resolveFile("npcdata.json"); + + -- If an invalid path, end now + if (p == nil) then + return + end + + -- Create the table and open the file + local f = io.open (p, "r"); + local str = f:read ("*all") + + -- Parse the data on a line-by-line basis + pcall(function () npcParse.externalJson = lunajson.decode(str) end) +end + + +-- Call this function to check whether a given NPC has been parsed yet and whether it was successful; +-- returns nil if not parsed, false if unsuccessful attempt and true if successful parsing +function npcParse.getSuccessful (pnpcRef) + if pnpcRef.data.npcParse ~= nil then + return pnpcRef.data.npcParse.success + else + return nil + end +end + + +-- Call this function to parse non-NPC.msg strings +local function getStringTable (str) + local data = nil + + -- Parse with the configured method + if useLoadstring then + + -- Ensure the string starts with a curly bracket, otherwise leave data nil + if string.sub(str, 1,1) == "{" then + + -- Load the table string + local f, errorStr = loadstring ("return "..str); + + -- Does the parsed table return any errors? + if f == nil then + return nil, errorStr + end + + -- Get the table + data = f() + end + + else + -- If parsing the table would cause an error, leave data nil + pcall(function () data = lunajson.decode(str) end) + end + + + -- Validation check 2: make sure the parsed code functions as a table + if type(data) == "table" then + + -- Return the table + return data, "TABLE SUCCESSFULLY PARSED" + else + return nil, "ERROR: NOT RECOGNIZED AS A TABLE" + end +end + +-- Call this function to parse a specific NPC +function npcParse.loadMsgData (npc, force) + + -- Only wrap non-generators until that pnpc bug is fixed + if npc:mem(0x64, FIELD_BOOL) == false then + + -- Wrap for the reference + local pnpcRef = pnpc.wrap (npc) + + -- Initialize the parse data + local parseData = {} + + -- Determine where the message string should be copied from and whether it should be parsed and loaded + parseData.success = npcParse.getSuccessful(pnpcRef) + local shouldLoad = true + + if parseData.success == nil then + areAllLoaded = false + parseData.msg = npc.msg.str + else + parseData.msg = pnpcRef.data.npcParse.msg or "" + parseData.success = pnpcRef.data.npcParse.success + shouldLoad = force + end + + + -- Parse and load the table if necessary/forced + if shouldLoad then + + -- Get data table + local dataTable = getStringTable (parseData.msg) + + -- Get other data from external json (all NPCs) + if npcParse.externalJson["_ALL"] ~= nil then + local extData = npcParse.externalJson["_ALL"] + for k,v in pairs (extData) do + pnpcRef.data[k] = v + end + end + + -- If a valid table, split master data table up into separate pnpc data tables and load data from external JSON + if dataTable ~= nil then + + -- In-message properties + for k,v in pairs (dataTable) do + pnpcRef.data[k] = v + end + + -- Get other data from external json (all IDed NPCs) + if npcParse.externalJson["_ID"] ~= nil and dataTable.id ~= nil then + local extData = npcParse.externalJson["_ID"] + for k,v in pairs (extData) do + pnpcRef.data[k] = v + end + end + + -- Get other data from external json + if npcParse.externalJson [dataTable.id] ~= nil then + local extData = npcParse.externalJson [dataTable.id] + for k,v in pairs (extData) do + pnpcRef.data[k] = v + end + end + parseData.success = true + + -- Store reference in the appropriate id group + if dataTable.id ~= nil then + if npcParse.idGroups[dataTable.id] == nil then + npcParse.idGroups[dataTable.id] = {} + end + local alreadyIndexed = false + for _, value in pairs(npcParse.idGroups[dataTable.id]) do + if value == pnpcRef then + alreadyIndexed = true + end + end + if not alreadyIndexed then + table.insert(npcParse.idGroups[dataTable.id], pnpcRef) + end + end + + + -- Clear the NPC's message string after successful loading if configured to do so + if npcParse.clearAfter == true then + + if pnpcRef.data.newMsg ~= nil then + npc.msg = pnpcRef.data.newMsg + else + npc.msg = "" + end + end + end + + -- add parseData as this library's data + pnpcRef.data.npcParse = parseData + end + end +end + +-- Call this function to parse all NPCs +function npcParse.loadAllMsgData (force) + for k,v in pairs(NPC.get()) do + npcParse.loadMsgData (v, force) + end + + areAllLoaded = true +end + +-- Check whether all NPCs are loaded +function npcParse.allLoaded () + return areAllLoaded; +end + + + +-- Update npcParse +local function updateParsing () + for k,v in pairs(NPC.get()) do + if npcParse.getSuccessful (pnpc.wrap(v)) == nil then + areAllLoaded = false + break; + end + end + + if npcParse.active == true and areAllLoaded == false then + npcParse.loadAllMsgData () + end +end + +-- Call update in onStart and then at the beginning and end of every tick +function npcParse.onStartStart () + loadExternalJson () + updateParsing () +end +function npcParse.onStartEnd () + updateParsing () +end +function npcParse.onTickStart () + --updateParsing () +end +function npcParse.onTickEnd () + --updateParsing () +end + + +-- Debug stuff +function npcParse.onCameraUpdate (eventObj, cameraIndex) + + if npcParse.debug ~= true then return; end; + + -- Draw the tables + local cam = Camera.get()[cameraIndex] + + for k,v in pairs (NPC.get()) do + local pnpcRef = pnpc.wrap (v) + local within = v.x > cam.x+128 and v.x < cam.x+cam.width-128 and v.y > cam.y+96 and v.y < cam.y+cam.height-96 + + if pnpcRef.data ~= nil and textbloxActive and within then + textblox.printTable (pnpcRef.data, + {x = pnpcRef.x, + y = math.floor(pnpcRef.y/16)*16 - 32, + bind = textblox.BIND_LEVEL, + halign = textblox.ALIGN_LEFT, + valign = textblox.ALIGN_BOTTOM, + font = textblox.FONT_SPRITEDEFAULT4}) + end + end +end + + +return npcParse \ No newline at end of file diff --git a/LuaScriptsLibExt/raocoin2.lua b/LuaScriptsLibExt/raocoin2.lua index 598429230..d3ede494d 100644 --- a/LuaScriptsLibExt/raocoin2.lua +++ b/LuaScriptsLibExt/raocoin2.lua @@ -34,7 +34,7 @@ --------------------Created by Hoeloe - 2015------------------- -------------Open-Source Currency and Shop Library------------- ---------------------For Super Mario Bros X-------------------- -----------------------------v2.0.8----------------------------- +---------------------------v2.0.10----------------------------- ----------------------REQUIRES ENCRYPT.dll--------------------- ---------------------REQUIRES COLLIDERS.lua-------------------- -----------------------REQUIRES PNPC.lua----------------------- @@ -354,8 +354,9 @@ function raocoin.update() end]] if(memcurrencyCache[v.id] < mem(v.id,v.type)) then - raocoin.onCollect(v, currencyCache[k].lastCount - currencyCache[k].count); - v:onCollect(currencyCache[k].lastCount - currencyCache[k].count); + + raocoin.onCollect(v, mem(v.id,v.type) - memcurrencyCache[k]); + v:onCollect(mem(v.id,v.type) - memcurrencyCache[k]); end memcurrencyCache[v.id] = mem(v.id,v.type); end @@ -383,7 +384,7 @@ function raocoin.update() if(doBuyAnim) then player:mem(0x122,FIELD_WORD,7); --Set state to "going through door" - player.y = sourceY+35-player.height; + player.y = sourceY+32-player.height; if(player:mem(0x12A,FIELD_WORD) >= 16440) then --Warp timer counts from 16368 to 16444 by twos. 16440 is an acceptable buffer to ensure it doesn't try to warp, which will crash the game. player:mem(0x122,FIELD_WORD,0); player:mem(0x12A,FIELD_WORD,0); @@ -398,16 +399,15 @@ function raocoin.update() if(not k:isBought()) then --npc icon - if(v.npc == nil and v.npcID ~= nil and v.enableTimer <= 0) then - n = pnpc.wrap(spawnNPC(v.npcID,v.x,v.y-70-64,v.section)); - n:mem(0x46,FIELD_WORD,0xFFFF); - n:mem(0x48,FIELD_WORD,0xFFFF); - n:mem(0x12A,FIELD_WORD,100); - n.speedX = 0; - n.speedY = 0; - v.npc = n; + if((v.npc == nil or not v.npc.isValid) and v.npcID ~= nil and v.enableTimer <= 0) then + v.npc = pnpc.wrap(NPC.spawn(v.npcID,v.x,v.y-70-64,v.section)); + v.npc:mem(0x46,FIELD_WORD,0xFFFF); + v.npc:mem(0x48,FIELD_WORD,0xFFFF); + v.npc:mem(0x12A,FIELD_WORD,100); + v.npc.speedX = 0; + v.npc.speedY = 0; end - if(v.npc ~= nil) then + if(v.npc ~= nil and v.npc.isValid) then v.npc.x = v.npc:mem(0xA8,FIELD_DFLOAT); v.npc.y = v.npc:mem(0xB0,FIELD_DFLOAT); v.npc.speedX = 0; @@ -424,14 +424,14 @@ function raocoin.update() --bmp icon if(v.image ~= nil and v.enableTimer <= 0) then - Graphics.drawImageWP(v.image,v.x,v.y-70-64,1); + Graphics.drawImageWP(v.image,v.x,v.y-70-64,-1); end --text if(v.text ~= nil and v.enableTimer <= 0) then table.insert(drawQueue, function() local x1,y1 = raocoin.worldToScreen(v.x+12,v.y-72); - Text.printWP(v.text,x1+8-string.len(v.text)*9,y1-26,1); + Text.printWP(v.text,x1+8-string.len(v.text)*9,y1-26,-1); end); end @@ -456,7 +456,7 @@ function raocoin.update() Audio.playSFX(getSMBXPath().."\\LuaScriptsLib\\raocoin\\buy.ogg"); spawnEffect(132,v.x,v.y); v.enableTimer = 50; - if(v.npc ~= nil) then + if(v.npc ~= nil and v.npc.isValid) then v.npc:mem(0x40,FIELD_WORD,0xFFFF); v.npc = nil; end diff --git a/LuaScriptsLibExt/smoovement.lua b/LuaScriptsLibExt/smoovement.lua new file mode 100644 index 000000000..ba9cfa401 --- /dev/null +++ b/LuaScriptsLibExt/smoovement.lua @@ -0,0 +1,229 @@ +--smoovement.lua +--by Spinda +--v1.1 + +local vectr = API.load("vectr"); + +local smoovement = {}; + +smoovement.customDraw = false; + +smoovement.customTick = false; + +smoovement.world = {transform = vectr.id3, children = {}, actualPriority = 0}; + +function smoovement.translateM(x, y) -- creates a matrix for translation + return vectr.mat3( {1, 0, x}, + {0, 1, y}, + {0, 0, 1}); +end; + +function smoovement.rotateM(s1,c1) -- creates a matrix for rotation + return vectr.mat3( {c1, -s1, 0}, + {s1, c1, 0}, + {0, 0, 1}); +end; + +function smoovement.scaleM(x,y) -- creates a matrix for scaling + return vectr.mat3( {x, 0, 0}, + {0, y, 0}, + {0, 0, 1}); +end; + +function smoovement.vectorTransToXY(vector, trans) -- turns a vector2 and a transformation into an x and y value + local v3 = trans * vectr.v3(vector.x,vector.y,1); + return v3.x, v3.y; +end; + +local function drawImageTransformed(t) + local img = t.img; -- setting values + local trans = t.transform or vectr.id3; + local p = t.actualPriority; + local w = img.width; + local h = img.height; + local pivX = t.pivotX or .5; + local pivY = t.pivotY or .5; + local o = t.opacity or 1; + local sceneC = t.usesSceneCoords; + local vertCoords = {}; + local w1 = - pivX * w; -- setting values so that the pivot is the center + local w2 = w + w1; + local h1 = -pivY * h; + local h2 = h + h1; + vertCoords[0], vertCoords[1] = smoovement.vectorTransToXY(vectr.v2(w1,h1), trans); -- setting vertex coordinates + vertCoords[2], vertCoords[3] = smoovement.vectorTransToXY(vectr.v2(w1,h2), trans); + vertCoords[4], vertCoords[5] = smoovement.vectorTransToXY(vectr.v2(w2,h1), trans); + vertCoords[6], vertCoords[7] = smoovement.vectorTransToXY(vectr.v2(w2,h2), trans); + vertCoords[8], vertCoords[9] = smoovement.vectorTransToXY(vectr.v2(w1,h2), trans); + vertCoords[10], vertCoords[11] = smoovement.vectorTransToXY(vectr.v2(w2,h1), trans); + local textCoords = {}; + textCoords[0] = 0; textCoords[1] = 0; -- setting texture coordinates + textCoords[2] = 0; textCoords[3] = 1; + textCoords[4] = 1; textCoords[5] = 0; + textCoords[6] = 1; textCoords[7] = 1; + textCoords[8] = 0; textCoords[9] = 1; + textCoords[10] = 1; textCoords[11] = 0; + Graphics.glDraw{texture = img, + vertexCoords = vertCoords, + textureCoords = textCoords, + color = {1, 1, 1, o}, + priority = p, + sceneCoords = sceneC}; -- drawing the image +end + +local function deleteChildren(sprite, delete) -- deleting sprites recursively + if deleted then sprite.deleted = true; end; + for i = #sprite.children, 1, -1 do + deleteChildren(sprite.children[i],delete or sprite.deleted); + if delete or sprite.deleted then + table.remove(sprite.children,i); + end; + end; +end; + +local function transformChildren(sprite) -- transforming sprites recursively so the transform of its parents get taken over for their children + for _,v in pairs(sprite.children) do + v.transform = sprite.transform * smoovement.translateM(v.x, v.y) * smoovement.scaleM(v.scaleX, v.scaleY) * smoovement.rotateM(math.sin(v.rotation * math.pi/180), math.cos(v.rotation * math.pi/180)); + v.actualPriority = v.priority + sprite.actualPriority; + transformChildren(v); + end; +end; + +local function drawChildren(sprite) -- drawing the sprites + for _,v in pairs(sprite.children) do + if v.hasAnimation then + v.counter = (v.counter + 1) % v.dTime; + if v.counter == 0 then + v.frame = v.frame % #v.frames + 1; + v.img = v.frames[v.frame]; + v.width = v.img.width; + v.height = v.img.height; + end; + end; + if v.img ~= nil and v.visible then + drawImageTransformed(v); + end; + drawChildren(v); + end; +end; + +local function contains(t,val) + for _, v in pairs(t) do + if v == val then return true; end; + end; + return false; +end; + +function smoovement.tick() + deleteChildren(smoovement.world,false); + transformChildren(smoovement.world); +end; + +function smoovement.draw() + drawChildren(smoovement.world); +end; + +function smoovement.onInitAPI() + registerEvent(smoovement,"onDraw","onDraw",false); + registerEvent(smoovement,"onTick","onTick",false); +end + +function smoovement.onDraw() + if not smoovement.customDraw then + smoovement.draw(); + end; +end; + +function smoovement.onTick() + if not smoovement.customTick then + smoovement.tick(); + end; +end; + +function smoovement.createSprite(t) + local newSpr = {img = t.img, + x = t.x or 0, + y = t.y or 0, + rotation = t.rotation or 0, + pivotX = t.pivotX or .5, + pivotY = t.pivotY or .5, + scaleX = t.scaleX or 1, + scaleY = t.scaleY or 1, + visible = t.visible, + usesSceneCoords = usesSceneCoords, + hasParent = false, + hasAnimation = false, + dTime = 0, + counter = 0, + frame = 1, + priority = t.priority or 0, + opacity = t.opacity, + parent = smoovement.world, + frames = {}, + children = {}, + actualPriority = 0, + transform = vectr.id3, + deleted = false, + _isSprite = true}; + if newSpr.visible == nil then newSpr.visible = true; end; + if newSpr.usesSceneCoords == nil then newSpr.usesSceneCoords = false; end; + if newSpr.img ~= nil then + newSpr.height = t.height or newSpr.img.height; + newSpr.width = t.width or newSpr.img.width; + else + newSpr.height = t.height or 0; + newSpr.width = t.width or 0; + end; + + newSpr.setScale = function(self, scaleX, scaleY) -- defining methods to make setting certain values faster + self.scaleX = scaleX; self.scaleY = scaleY; + end; + newSpr.setPivot = function(self, pivotX, pivotY) + self.pivotX = pivotX; self.pivotY = pivotY; + end; + newSpr.moveTo = function(self, x, y) + self.x = x; self.y = y; + end; + newSpr.setParent = function(self, parent) -- method to set a parent + for i = #self.parent.children, 1, -1 do -- removing sprite from children table of the previous parent + if self == self.parent.children[i] then + table.remove(self.parent.children,i); + break; + end; + end; + self.parent = parent; + table.insert(self.parent.children,self); + self.hasParent = true; + end; + newSpr.removeParent = function(self) + self.hasParent = false; + for i = #self.parent.children, 1, -1 do -- removing sprite from childen table of the previous paeent + if self == self.parent.children[i] then + table.remove(self.parent.children,i); + break; + end; + end; + end; + newSpr.setAnimation = function(self, tab, dTime) + self.hasAnimation = true; + self.frames = tab; + self.dTime = dTime; + self.counter = 0; + self.frame = 1; + self.width = self.frames[1].width; + self.height = self.frames[1].height; + end; + newSpr.setSprite = function(self, sprite) + self.hasAnimation = false; + self.img = sprite; + self.height = self.img.height; + self.width = self.img.width; + end; + newSpr.delete = function(self) + self.deleted = true; + end; + table.insert(smoovement.world.children,newSpr); + return newSpr; +end; + +return smoovement; \ No newline at end of file diff --git a/LuaScriptsLibExt/vectr.lua b/LuaScriptsLibExt/vectr.lua index 35eea9f5a..b1ac88de2 100644 --- a/LuaScriptsLibExt/vectr.lua +++ b/LuaScriptsLibExt/vectr.lua @@ -9,7 +9,7 @@ ------Created by Hoeloe - 2015------ -----Open-Source Vector Library----- -------For Super Mario Bros X------- -----------------v1.0a--------------- +----------------v1.0---------------- local vectr = {}; local version = "1.0"; @@ -27,56 +27,14 @@ end do --Vector 2 ---CLASS DEF -local vect2 = {}; +--METATABLE +local createmt2; local v2mt = {}; - -function vect2.normalise(a) - if(a.sqrlength == 0) then - return vectr.v2(0,0) - elseif(a.sqrlength == 1) then - return a; - else - return vectr.v2(a.x/a.length,a.y/a.length); - end -end - -function vect2.rotate(a,d) - local r = d*0.0174534; --deg2rad - local sr = math.sin(r); - local cr = math.cos(r); - return vectr.v2(a.x*cr - a.y*sr, a.x*sr + a.y*cr); -end - -function vect2.lookat(a,x1,y1) - local v; - local t = v2mt_typecheck(x1); - if(t == "number") then - v = vectr.v2(x1,y1):normalise(); - else - v = x1:normalise(); - end - return v*a.length; -end - -function vect2.tov3(a) - return vectr.v3(a.x,a.y,0); -end - -function vect2.tov4(a) - return vectr.v3(a.x,a.y,0,0); -end - -function vect2.dot(a,b) +function v2mt.dot(a,b) return a.x*b.x + a.y*b.y end -vect2.normalize = vect2.normalise; -vect2.project = proj; - ---METATABLE - -local function v2mt_typecheck(a) +function v2mt.typecheck(a) if(type(a) == "number") then return "number"; elseif(a._type ~= nil and a._type == "vector2") then @@ -86,23 +44,9 @@ local function v2mt_typecheck(a) end end -function v2mt.__index(obj,key) - if(key == "x") then return rawget(obj, "x") - elseif(key == "y") then return rawget(obj, "y") - elseif(key == "sqrlength") then - return obj.x*obj.x + obj.y*obj.y - elseif(key == "length") then - return math.sqrt(obj.x*obj.x + obj.y*obj.y) - elseif(key == "_type") then - return "vector2"; - else - return vect2[key] - end -end - -function v2mt.__newindex(obj,key,val) - if(key == "x") then rawset(obj, "x", val); - elseif(key == "y") then rawset(obj, "y", val); +function v2mt.newindex(obj,key,val) + if(key == "x") then setmetatable(obj,createmt2(val,obj.y)) + elseif(key == "y") then setmetatable(obj,createmt2(obj.x,val)) elseif(key == "length" or key == "sqrlength") then error("Cannot set the length of a vector directly. Try changing the component values.",2) elseif(key == "_type") then @@ -112,13 +56,13 @@ function v2mt.__newindex(obj,key,val) end end -function v2mt.__tostring(obj) +function v2mt.tostring(obj) return "("..tostring(obj.x)..", "..tostring(obj.y)..")" end -function v2mt.__add(a,b) - local ta = v2mt_typecheck(a); - local tb = v2mt_typecheck(b); +function v2mt.add(a,b) + local ta = v2mt.typecheck(a); + local tb = v2mt.typecheck(b); if(ta == "number") then if(tb == "number") then return a+b; @@ -132,9 +76,9 @@ function v2mt.__add(a,b) end end -function v2mt.__sub(a,b) - local ta = v2mt_typecheck(a); - local tb = v2mt_typecheck(b); +function v2mt.sub(a,b) + local ta = v2mt.typecheck(a); + local tb = v2mt.typecheck(b); if(ta == "number") then if(tb == "number") then return a-b; @@ -148,13 +92,13 @@ function v2mt.__sub(a,b) end end -function v2mt.__unm(a) +function v2mt.neg(a) return vectr.v2(-a.x,-a.y) end -function v2mt.__mul(a,b) - local ta = v2mt_typecheck(a); - local tb = v2mt_typecheck(b); +function v2mt.mul(a,b) + local ta = v2mt.typecheck(a); + local tb = v2mt.typecheck(b); if(ta == "number") then if(tb == "number") then return a*b; @@ -168,9 +112,9 @@ function v2mt.__mul(a,b) end end -function v2mt.__div(a,b) - local ta = v2mt_typecheck(a); - local tb = v2mt_typecheck(b); +function v2mt.div(a,b) + local ta = v2mt.typecheck(a); + local tb = v2mt.typecheck(b); if(ta == "number") then if(tb == "number") then return a/b; @@ -184,7 +128,7 @@ function v2mt.__div(a,b) end end -function v2mt.__eq(a,b) +function v2mt.equals(a,b) if(a == nil or b == nil or typecheck(a) ~= "vector2" or typecheck(b) ~= "vector2") then return false; else @@ -192,26 +136,115 @@ function v2mt.__eq(a,b) end end -function v2mt.__len(a) +function v2mt.len(a) return 2; end -v2mt.__concat = vect2.dot; -v2mt.__mod = proj; +createmt2 = function(x,y,sl,l) + local mt = {} + mt.__index = + function(obj,key) + if(key == "x") then return x + elseif(key == "y") then return y + elseif(key == "sqrlength") then + if(sl == nil) then + local sm = x*x + y*y; + setmetatable(obj,createmt2(x,y,sm)); + return sm; + else + return sl; + end + elseif(key == "length") then + if(l == nil) then + local sm = sl or (x*x + y*y); + local mag = math.sqrt(sm); + setmetatable(obj,createmt2(x,y,sm,mag)); + return mag; + else + return l; + end + elseif(key == "_type") then + return "vector2"; + else + return nil; + end + end + mt.__newindex = v2mt.newindex; + mt.__tostring = v2mt.tostring; + mt.__add = v2mt.add; + mt.__sub = v2mt.sub; + mt.__unm = v2mt.neg; + mt.__mul = v2mt.mul; + mt.__div = v2mt.div; + mt.__concat = v2mt.dot; + mt.__mod = proj; + mt.__eq = v2mt.equals; + mt.__len = v2mt.len; + --mt.__metatable = mthide; + + return mt; +end + +--CLASS DEF +local vect2 = {}; +function vect2.normalise(a) + if(a.sqrlength == 0) then + return vectr.v2(0,0) + elseif(a.sqrlength == 1) then + return a; + else + return vectr.v2(a.x/a.length,a.y/a.length); + end +end + +function vect2.rotate(a,d) + local r = d*0.0174534; --deg2rad + local sr = math.sin(r); + local cr = math.cos(r); + return vectr.v2(a.x*cr - a.y*sr, a.x*sr + a.y*cr); +end + +function vect2.lookat(a,x1,y1) + local v; + local t = v2mt.typecheck(x1); + if(t == "number") then + v = vectr.v2(x1,y1):normalise(); + else + v = x1:normalise(); + end + return v*a.length; +end + +function vect2.tov3(a) + return vectr.v3(a.x,a.y,0); +end + +function vect2.tov4(a) + return vectr.v3(a.x,a.y,0,0); +end + +vect2.normalize = vect2.normalise; +vect2.dot = v2mt.dot; +vect2.project = proj; --CONSTRUCTOR function vectr.v2(x,y) + local v = {}; + + for m,n in pairs(vect2) do + v[m] = n; + end + if(type(x) == "number") then y = y or x; elseif(x ~= nil and x._type ~= nil and x._type == "vector2") then y = x.y; x = x.x; else - error("Invalid vector definition.",2); + error("Invalid vector definition.",2) end - local v = {x=x, y=y}; - setmetatable(v, v2mt); + setmetatable(v,createmt2(x,y)); return v; end diff --git a/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml b/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml new file mode 100644 index 000000000..fa2985746 --- /dev/null +++ b/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/misc.xml b/Tools/LunaLuaBindingsGenerator/.idea/misc.xml new file mode 100644 index 000000000..b96e85da1 --- /dev/null +++ b/Tools/LunaLuaBindingsGenerator/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/modules.xml b/Tools/LunaLuaBindingsGenerator/.idea/modules.xml new file mode 100644 index 000000000..bcd2386eb --- /dev/null +++ b/Tools/LunaLuaBindingsGenerator/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml b/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml new file mode 100644 index 000000000..e54df7b75 --- /dev/null +++ b/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1465201296244 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 48685edbd9938670ecbdbeac058b1903cf67786d Mon Sep 17 00:00:00 2001 From: Kevin Waldock Date: Wed, 14 Dec 2016 11:56:27 +0100 Subject: [PATCH 2/2] Remove IDE files which should not have been commited --- .../.idea/LunaLuaBindingsGenerator.iml | 14 - Tools/LunaLuaBindingsGenerator/.idea/misc.xml | 14 - .../.idea/modules.xml | 8 - .../.idea/workspace.xml | 266 ------------------ 4 files changed, 302 deletions(-) delete mode 100644 Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml delete mode 100644 Tools/LunaLuaBindingsGenerator/.idea/misc.xml delete mode 100644 Tools/LunaLuaBindingsGenerator/.idea/modules.xml delete mode 100644 Tools/LunaLuaBindingsGenerator/.idea/workspace.xml diff --git a/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml b/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml deleted file mode 100644 index fa2985746..000000000 --- a/Tools/LunaLuaBindingsGenerator/.idea/LunaLuaBindingsGenerator.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/misc.xml b/Tools/LunaLuaBindingsGenerator/.idea/misc.xml deleted file mode 100644 index b96e85da1..000000000 --- a/Tools/LunaLuaBindingsGenerator/.idea/misc.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/modules.xml b/Tools/LunaLuaBindingsGenerator/.idea/modules.xml deleted file mode 100644 index bcd2386eb..000000000 --- a/Tools/LunaLuaBindingsGenerator/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml b/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml deleted file mode 100644 index e54df7b75..000000000 --- a/Tools/LunaLuaBindingsGenerator/.idea/workspace.xml +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1465201296244 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file