Having some trouble with shootProjectile

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
Thorham
Posts: 80
Joined: Sat May 04, 2013 5:12 pm

Re: Having some trouble with shootProjectile

Post by Thorham »

AndakRainor wrote:Could you share your code ? I would like to compare. Thanks !
This creates missile and meteor spells for each element, and keeps track of which champion cast the spell (note that the meteor spawner object is only for the meteor spells):

Code: Select all

local missile = {
    {name = "Fireball", element = "fire", particle = "fireball_large", color = vec(1, 0.5, 0.25),
     hit = "fireball_blast_large", sound = "fireball", sound2 = "fireball_launch", gesture = 2, gesture2 = 25,
     icon = 61, spellIcon = 7,
     description = "A flaming ball of fire shoots from your fingertips causing devastating damage to your foes."},

    {name = "Frostbolt", element = "frost", particle = "frostbolt", color = vec(0.25, 0.5, 1),
     hit = "frostbolt_blast", sound = "frostbolt", sound2 = "frostbolt_launch", gesture = 8, gesture2 = 85,
     icon = 71, spellIcon = 4,
     description = "You hurl a bolt of icy death dealing ranged damage and freezing your opponents. Every point in Water Magic increases the probability and duration of the freezing effect."},

    {name = "Lightningbolt", element = "lightning", particle = "lightning_bolt", color = vec(0.25, 0.5, 1),
     hit = "lightning_bolt_blast", sound = "lightning_bolt", sound2 = "lightning_bolt_launch", gesture = 6, gesture2 = 65,
     icon = 65, spellIcon = 9,
     description = "You channel the power of storms through your hands."},

    {name = "Poisonbolt", element = "poison", particle = "poison_bolt", color = vec(0.25, 0.6, 0.2),
     hit = "poison_bolt_blast", sound = "poison_bolt", sound2 = "poison_bolt_launch", gesture = 4, gesture2 = 45,
     icon = 63, spellIcon = 10,
     description = "A sizzling venomous bolt of poison shoots from your hands."}
}

local castProjectile = function(party, champion, missile, hit, x, y, x1, y1, yr)
    local a = party:spawn(missile)
    a.projectile:setIgnoreEntity(party)
    a:setWorldPosition(party:getWorldPosition() + vec(-x + x1, 1.35 + yr, y + y1))
    a.script:setData(champion, hit)
end

defineObject{
    name = "meteorSpawner",
    placement = "floor",
    components = {
        {
            class = "Timer",
            onInit = function(self)
                self.go.timer:disable()
                self.go.timer:setTimerInterval(0.15)
                self.go.timer:setTriggerOnStart(true)
            end,

            onActivate = function(self)
                local x, y = getForward(party.facing)

                local xr = math.random() - 0.5
                local yr = math.random() - 0.5

                local x1 = (math.abs(x + 1) % 2) * xr
                local y1 = (math.abs(y + 1) % 2) * xr

                local champion, spell, amount, hit = self.go.script:getCast()

                castProjectile(party, champion, spell, hit, x, y, x1, y1, yr)

                if self.go.script:decAmount() == 0 then
                    self.go:destroy()
                end
            end
        },
        {
            class = "Controller",
            onActivate = function(self)
                self.go.timer:enable()
                self.go.timer:start()
            end
        },
        {
            class = "Script",
            source = [[
                champion = 0
                spell = ""
                amount = 0
                hit = ""

                function setCast(caller, a, b, c, d)
                    champion = a
                    spell = b
                    amount = c
                    hit = d
                end
                function getCast()
                    return champion, spell, amount, hit
                end
                function decAmount()
                    amount = amount - 1
                    return amount
                end
            ]]
        }
    }
}

local i
for i = 1, 4 do
--
-- Single missile
--
    defineSpell{
        name = missile[i].element.."MissileSpell",
        uiName = missile[i].name,
        gesture = missile[i].gesture,
        manaCost = 1,
        icon = missile[i].icon,
        spellIcon = missile[i].spellIcon,
        description = missile[i].description,

        onCast = function(champion, x, y, direction, elevation, skillLevel)
            local x, y = getForward(party.facing)
            local spell = missile[i].element.."missileObject"
            local hit = missile[i].hit
            castProjectile(party, champion:getOrdinal(), spell, hit, x, y, 0, 0, 0)
        end,
    }
--
-- Meteor style missiles.
--
    defineSpell{
        name = missile[i].element.."MeteorSpell",
        uiName = missile[i].name,
        gesture = missile[i].gesture2,
        manaCost = 1,
        icon = missile[i].icon,
        spellIcon = missile[i].spellIcon,
        description = missile[i].description,

        onCast = function(champion, x, y, direction, elevation, skillLevel)
            local a = party:spawn("meteorSpawner")
            local spell = missile[i].element.."missileObject"
            local hit = missile[i].hit
            a.script:setCast(champion:getOrdinal(), spell, 5, hit)
            a.controller:activate()
        end,
    }

    defineObject{
        name = missile[i].element.."missileObject",
        baseObject = "base_spell",
        components = {
            {
                class = "Particle",
                particleSystem = missile[i].particle,
            },
            {
                class = "Light",
                color = missile[i].color,
                brightness = 15,
                range = 7,
                castShadow = true,
            },
            {
                class = "Projectile",
                spawnOffsetY = 1.35,
                velocity = 10,
                radius = 0.1,

                onProjectileHit = function(self, what, entity)
                    local champNum, hit = self.go.script:getData()
                    local champion = party.party:getChampionByOrdinal(champNum)
                    local a = self.go:spawn(hit)
                    a:setWorldPosition(self.go:getWorldPosition())
                    a.tiledamager:setCastByChampion(champNum)
                    a.tiledamager:setAttackPower(30 + 30/100 * 20 * champion:getSkillLevel("fire_magic"))
                end,
            },
            {
                class = "Sound",
                sound = missile[i].sound,
            },
            {
                class = "Sound",
                name = "launchSound",
                sound = missile[i].sound2,
            },
            {
                class = "Script",
                source = [[
                    champion = 0
                    hit = ""
                    function setData(caller, a, b)
                        champion = a
                        hit = b
                    end
                    function getData()
                        return champion, hit
                    end
                ]]
            }
        }
    }
end
I don't know if I'm happy with that code, though...
Post Reply