Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if MinigameSnowball == nil then
- MinigameSnowball = class({})
- end
- SNOWBALL_FALL_HEIGHT = 0
- SNOWBALL_SIZE = 100
- SNOWBALL_MODEL_RADIUS = 128
- SNOWBALL_KILL_INTERVAL = 0.2
- SNOWBALL_BEGIN_TIME = 80
- SNOWBALL_BONUS_TIME = 10
- function MinigameSnowball:InitMinigame()
- print("[OMNIPARTY] Run Maiden, Run!")
- -- Set scoring method
- OmniParty:AutoScoreReverse()
- -- Initialize areas
- self._PlayerSpawn = GetArea("snowball_player_spawn")
- self._CheckPoint = {
- [0] = self._PlayerSpawn,
- [1] = GetArea("real_snowball_checkpoint_1"),
- [2] = GetArea("real_snowball_checkpoint_2"),
- -- [3] = GetArea("snowball_checkpoint_3")
- }
- self._WardPosition = Entities:FindAllByName("snowball_vision")
- for i, v in pairs(self._WardPosition) do
- self._WardPosition[i] = self._WardPosition[i]:GetAbsOrigin()
- end
- -- Show the remaining time
- Scoreboard:ShowExtraColumn("#time")
- -- Initialize Maidens
- self._SnowMaiden = {}
- self._SnowMaidenCount = 0
- self._LastCheckPoint = {}
- self._TimeCheckPoint = {}
- self._Countdown = {}
- for i, player in pairs(GetPlayers()) do
- self._SnowMaiden[i] = SpawnUnitForPlayer("npc_snow_maiden", player, self._PlayerSpawn, 0, true, false, 80, true)
- ApplyCustomModifier(self._SnowMaiden[i], "item_modifier", "no_collision")
- self._SnowMaidenCount = self._SnowMaidenCount + 1
- self._LastCheckPoint[i] = 0
- self._TimeCheckPoint[i] = 0
- self._Countdown[i] = SNOWBALL_BEGIN_TIME
- Scoreboard:SetPlayerExtra(i, self._Countdown[i])
- PlayerResource:SetCameraTarget(i, self._SnowMaiden[i])
- end
- -- Initialize Snowballs
- local Snowball_param = self:GetSnowballParam()
- -- Get the starting and destination points for all the snowballs
- local _max_s = {}
- local _max_n = {}
- local count = {}
- for k, group in pairs(Snowball_param) do
- count[k] = 0
- for i, v in pairs(group) do
- -- Get start and end positions for the snowballs
- v.start = Entities:FindByName(nil, "snowball_start_" .. i):GetAbsOrigin()
- v.dest = Entities:FindByName(nil, "snowball_dest_" .. i):GetAbsOrigin()
- v.start[3]=128
- v.dest[3]=128
- -- Precalculate number and size of series
- if _max_s[k] == nil then
- _max_s[k] = #v.velocity
- end
- _max_n[i] = {}
- for j, series in pairs(v.velocity) do
- _max_n[i][j] = #series
- end
- count[k] = count[k] + 1
- end
- end
- -- Create Snowball spawners
- self._SnowballTimer = {}
- for k, group in pairs(Snowball_param) do
- local max_s = _max_s[k]
- local s = RandomInt(1, max_s)
- local flag = count[k]
- for i, v in pairs(group) do
- local max_n = _max_n[i][s]
- local n = 0
- self._SnowballTimer[i] = Timers:CreateTimer({
- callback = function()
- n = n + 1
- if n > max_n then
- if flag == count[k] then
- s = RandomInt(1, max_s)
- flag = 1
- else
- flag = flag + 1
- end
- max_n = _max_n[i][s]
- n = 1
- end
- if v.velocity[s][n] ~= 0 then
- self:CreateSnowball(SNOWBALL_SIZE, v.start, v.velocity[s][n] * (v.dest - v.start):Normalized(),
- (v.dest - v.start):Length())
- end
- return v.interval[s][n]
- end
- })
- end
- end
- end
- function MinigameSnowball:Intro()
- Scoreboard:ShowHelp("#snowball")
- end
- function MinigameSnowball:OnUnitDeath(keys)
- local unit = EntIndexToHScript(keys.entindex_killed)
- local name = unit:GetUnitName()
- if name == "npc_snow_maiden" then
- local killer = EntIndexToHScript(keys.entindex_attacker)
- local player = unit:GetPlayerOwner()
- local id = unit:GetPlayerOwnerID()
- -- If the player died to a snowball respawn
- if player and killer:GetUnitName() == "npc_dummy" and IsPhysicsUnit(killer) then
- local posspawn = RandomVectorInArea(self._CheckPoint[self._LastCheckPoint[id]],50,50)
- self._SnowMaiden[id] = SpawnUnitForPlayer("npc_snow_maiden", player,
- posspawn, 0, false, false, 80, true)
- end
- end
- end
- function SetCheckPoint(trigger)
- OmniParty._Minigame:SetCheckPoint(trigger.activator, trigger.caller)
- end
- function MinigameSnowball:SetCheckPoint(unit, area)
- if unit:GetUnitName() == "npc_snow_maiden" then
- local areaName = area:GetName()
- local n = string.gsub(area:GetName(), "%D", "")
- n = tonumber(n)
- local id = unit:GetPlayerOwnerID()
- if self._LastCheckPoint[id] < n then
- self._LastCheckPoint[id] = n
- self._TimeCheckPoint[id] = self._Countdown[id]
- self._Countdown[id] = self._Countdown[id] + SNOWBALL_BONUS_TIME
- Announcement:Player(id, "Checkpoint reached!", 3)
- end
- end
- end
- function PlayerFinished(trigger)
- OmniParty._Minigame:PlayerFinished(trigger.activator)
- end
- function MinigameSnowball:PlayerFinished(unit)
- if unit:GetUnitName() == "npc_snow_maiden" then
- local id = unit:GetPlayerOwnerID()
- RemoveWinner(unit)
- OmniParty:AutoScore(id)
- self._LastCheckPoint[id] = -1
- self._Countdown[id] = -1
- local player = unit:GetPlayerOwner()
- local id = unit:GetPlayerOwnerID()
- if player then
- for i, position in pairs(self._WardPosition) do
- CreateWard(WARD_GROUND, position, player)
- end
- end
- Scoreboard:SetPlayerExtra(id, nil)
- self._SnowMaiden[id] = nil
- self._SnowMaidenCount = self._SnowMaidenCount - 1
- end
- end
- function MinigameSnowball:CreateSnowball(r_kill, position, velocity, distance)
- -- print(position)
- local Snowball = CreateUnitByName("npc_dummy", position, true, nil, nil, DOTA_TEAM_NEUTRALS)
- -- Calculate the model scale according to the kill radius it should have
- local scale = r_kill / SNOWBALL_MODEL_RADIUS * 2
- -- Roll radius so that the snowball rolls a bit submerged in the ground
- local r_roll = scale * (SNOWBALL_MODEL_RADIUS - 100)
- -- Initialize physics properties
- Physics:Unit(Snowball)
- Snowball:Hibernate(false)
- Snowball:SetPhysicsFriction(0)
- -- Make the ball fall before starting the intended movement
- Snowball:SetAbsOrigin(GetGroundPosition(position, Snowball) + Vector(0, 0, SNOWBALL_FALL_HEIGHT))
- Snowball:SetPhysicsVelocity(Vector(0, 0, -1 * velocity:Length()))
- -- local pindex = ParticleManager:CreateParticle("particles/basic_rope/basic_rope.vpcf",
- -- PATTACH_ABSORIGIN, unit)
- -- Create the actual snowball model
- -- model = "models/props_gameplay/soccer_ball.vmdl",
- local SnowballModel = SpawnEntityFromTableSynchronous("prop_dynamic", {
- model = "models/props_consumables/balloons/donkey_dire_2022/donkey_dire_2022.vmdl",
- origin = Snowball:GetAbsOrigin() + Vector(0, 0, r_roll)
- })
- SnowballModel:SetModelScale(scale)
- -- Start with a random rotation
- SnowballModel:SetAngles(0, 180, 0)
- -- Snowball movement logic
- Snowball:OnPhysicsFrame(function(unit)
- local velocity = Snowball:GetPhysicsVelocity()
- local vel2D = Vector(velocity.x, velocity.y, 0)
- local speed = vel2D:Length()
- if speed > 1 then
- -- Calculate rotation angle based on velocity direction
- local rollAngle = speed * FrameTime() * 360 / (2 * math.pi * r_roll)
- local currentAngles = SnowballModel:GetAngles()
- local yawAngle = math.atan2(velocity.y, velocity.x) * 180 / math.pi
- SnowballModel:SetAngles(0,
- yawAngle,
- 0)
- end
- SnowballModel:SetAbsOrigin(Snowball:GetAbsOrigin() + Vector(0, 0, r_roll))
- if Snowball:GetPhysicsVelocity():Length() < 1 then
- Snowball:Destroy()
- SnowballModel:Destroy()
- end
- end)
- -- Snowball kill logic
- Timers:CreateTimer({
- callback = function()
- if IsValidEntity(Snowball) then
- -- DebugDrawCircle(Snowball:GetAbsOrigin(), Vector(255,0,0), 5.0, r_kill, true, 0.1)
- local squash = FindUnitsInRadius(DOTA_TEAM_NEUTRALS, Snowball:GetAbsOrigin(), nil, r_kill,
- DOTA_UNIT_TARGET_TEAM_ENEMY, DOTA_UNIT_TARGET_HERO, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER,
- false)
- for i, unit in pairs(squash) do
- unit:Kill(nil, Snowball)
- end
- return SNOWBALL_KILL_INTERVAL
- end
- end
- })
- -- Stop the snowball when it hits the ground and start the desired movement
- Timers:CreateTimer({
- endTime = SNOWBALL_FALL_HEIGHT / velocity:Length(),
- callback = function()
- -- Set intended direction
- Snowball:SetPhysicsVelocity(velocity)
- -- Stop the snowball after it has traveled the intended distance, which kills it
- Timers:CreateTimer({
- endTime = distance / velocity:Length(),
- callback = function()
- Snowball:SetPhysicsVelocity(Vector(0, 0, 0))
- end
- })
- end
- })
- end
- function MinigameSnowball:Destroy()
- -- Stop the snowball spawners
- for i, timer in pairs(self._SnowballTimer) do
- Timers:RemoveTimer(timer)
- end
- KillUnitList({"npc_ward_ground"})
- -- Score the players who didn't finish
- local score = {}
- for i, checkpoint in pairs(self._LastCheckPoint) do
- if checkpoint >= 0 then
- -- The score information can be combined
- score[i] = 1000 * checkpoint + self._TimeCheckPoint[i]
- end
- end
- OmniParty:AutoScoreFromArray(score, true)
- end
- function MinigameSnowball:MinigameThink()
- -- Check if the minigame is over
- if self._SnowMaidenCount == 0 then
- return
- end
- local allzero = true
- -- Display coundown
- for i, time in pairs(self._Countdown) do
- if time >= 0 then
- if time == 0 then
- self._SnowMaiden[i]:ForceKill(true)
- else
- Scoreboard:SetPlayerExtra(i, self._Countdown[i])
- end
- self._Countdown[i] = self._Countdown[i] - 1
- if self._Countdown[i] > 0 then
- allzero = false
- end
- end
- end
- if allzero then
- KillUnitList({"npc_snow_maiden"})
- return
- end
- return 1
- end
- function MinigameSnowball:GetSnowballParam()
- return {{
- [1] = {
- velocity = {{100}},
- interval = {{5.5}}
- }
- }, {
- [2] = {
- velocity = {{600, 900, 900}},
- interval = {{2, 1.5, 1.5}}
- }
- }, {
- [3] = {
- velocity = {{600}},
- interval = {{2.5}}
- },
- [4] = {
- velocity = {{600}},
- interval = {{2.5}}
- }
- }, {
- [5] = {
- velocity = {
- {600, 400, 400, 400},
- {600, 400, 400, 600}
- },
- interval = {
- {1, 1, 1, 2},
- {4, 4,4, 4}
- }
- }
- },
- {
- [6] = {
- velocity = {
- {0, 280, 280},
- {0, 280, 280, 280},
- {0, 280, 280, 280},
- {0, 280, 280}
- },
- interval = {
- {4*0.857, 0.857, 0.857},
- {0.857, 0.857, 4*0.857, 0.857},
- {0.857, 0.857, 4*0.857, 3*0.857},
- {3*0.857, 0.857, 3*0.857}
- }
- },
- [7] = {
- velocity = {
- {0, 280, 280},
- {0, 280},
- {0, 280, 280},
- {0, 280, 280}
- },
- interval = {
- {0.857, 0.857, 4*0.857},
- {4*0.857, 3*0.857},
- {4*0.857, 4*0.857, 0.857},
- {0.857, 5*0.857, 0.857}
- }
- },
- [8] = {
- velocity = {
- {280, 280},
- {280, 280, 280},
- {280, 280, 280, 280},
- {280, 280}
- },
- interval = {
- {4*0.857, 2*0.857},
- {0.857, 4*0.857, 2*0.857},
- {0.857, 2*0.857, 3*0.857, 3*0.857},
- {4*0.857, 3*0.857}
- }
- },
- [9] = {
- velocity = {
- {0, 280, 280},
- {0, 280, 280, 280},
- {0, 280, 280, 280},
- {0, 280, 280, 280}
- },
- interval = {
- {2*0.857, 2*0.857, 2*0.857},
- {2*0.857, 0.857, 3*0.857, 0.857},
- {3*0.857, 4*0.857, 0.857, 0.857},
- {2*0.857, 0.857, 2*0.857, 2*0.857}
- }
- }
- },
- {
- -- Right to left
- [10] = {
- velocity = {{600, 600, 600}},
- interval = {{2.5, 2.5, 7}}
- },
- [11] = {
- velocity = {{0}},
- interval = {{12}}
- },
- [12] = {
- velocity = {{0, 600, 600}},
- interval = {{1.25, 2.5, 8.25}}
- },
- [13] = {
- velocity = {{0}},
- interval = {{12}}
- },
- -- Left to right
- [14] = {
- velocity = {{0}},
- interval = {{12}}
- },
- [15] = {
- velocity = {{0, 600, 600}},
- interval = {{1.25, 2.5, 8.25}}
- },
- [16] = {
- velocity = {{0}},
- interval = {{12}}
- },
- [17] = {
- velocity = {{600, 600, 600}},
- interval = {{2.5, 2.5, 7}}
- },
- -- Top to bottom
- [18] = {
- velocity = {{0}},
- interval = {{12}}
- },
- [19] = {
- velocity = {{0, 300}},
- interval = {{9, 3}}
- }
- }
- -- [20] = {
- -- velocity = {{0}},
- -- interval = {{12}}
- -- },
- -- [21] = {
- -- velocity = {{0, 300}},
- -- interval = {{9, 3}}
- -- },
- -- -- Bottom to top
- -- [22] = {
- -- velocity = {{0, 300}},
- -- interval = {{9, 3}}
- -- },
- -- [23] = {
- -- velocity = {{0}},
- -- interval = {{11}}
- -- },
- -- [24] = {
- -- velocity = {{0, 300}},
- -- interval = {{9, 3}}
- -- },
- -- [25] = {
- -- velocity = {{0}},
- -- interval = {{12}}
- -- }
- -- },
- -- {
- -- -- Top to bottom
- -- [26] = {
- -- velocity = {{0, 400}},
- -- interval = {{0.75, 3.75}}
- -- },
- -- [27] = {
- -- velocity = {{0, 400}},
- -- interval = {{1.5, 3}}
- -- },
- -- [28] = {
- -- velocity = {{400}},
- -- interval = {{4.5}}
- -- },
- -- -- Bottom to top
- -- [29] = {
- -- velocity = {{0, 400}},
- -- interval = {{3, 1.50}}
- -- },
- -- [30] = {
- -- velocity = {{0, 400}},
- -- interval = {{3.75, 0.75}}
- -- },
- -- [31] = {
- -- velocity = {{0, 400}},
- -- interval = {{2.25, 2.25}}
- -- }
- -- },
- -- {
- -- -- Top to bottom
- -- [32] = {
- -- velocity = {{0, 300}},
- -- interval = {{0.75, 5.25}}
- -- },
- -- [33] = {
- -- velocity = {{0}},
- -- interval = {{6}}
- -- },
- -- -- Bottom to top
- -- [34] = {
- -- velocity = {{0, 300}},
- -- interval = {{3.75, 2.25}}
- -- },
- -- [35] = {
- -- velocity = {{300, 300, 300, 300}},
- -- interval = {{1.5, 1.5, 1.5, 1.5}}
- -- }
- -- }
- }
- end
- function printDebug(t, indent, done)
- -- Set default parameters
- done = done or {}
- indent = indent or 0
- local indentStr = string.rep(" ", indent)
- if type(t) ~= "table" then
- print(indentStr .. tostring(t))
- return
- end
- -- Avoid infinite recursion
- if done[t] then
- print(indentStr .. "TABLE *recursive*")
- return
- end
- done[t] = true
- -- Print each field with proper indentation
- for key, value in pairs(t) do
- if type(key) ~= "number" then
- key = '"' .. tostring(key) .. '"'
- end
- if type(value) == "table" and not done[value] then
- print(indentStr .. "[" .. key .. "] = {")
- printDebug(value, indent + 1, done)
- print(indentStr .. "}")
- elseif type(value) == "userdata" then
- print(indentStr .. "[" .. key .. "] = userdata")
- else
- print(indentStr .. "[" .. key .. "] = " .. tostring(value))
- end
- end
- end
- function InspectEntity(entity)
- print("[ENTITY INSPECTOR] Beginning entity inspection")
- -- Basic entity information
- print("[ENTITY INSPECTOR] Entity exists: " .. tostring(entity ~= nil))
- if not entity then
- return
- end
- -- Try common entity methods
- local methods = {"GetClassname", "GetName", "GetEntityName", "GetEntityIndex", "entindex", "GetEntityHandle",
- "GetAbsOrigin", "GetOrigin", "GetCenter", "GetAngles", "GetBoundingMaxs", "GetBoundingMins",
- "GetTargetName", "GetDebugName", "GetModelName", "IsValid"}
- for _, method in ipairs(methods) do
- if entity[method] then
- local success, result = pcall(function()
- return entity[method](entity)
- end)
- if success then
- if type(result) == "userdata" and result.x and result.y and result.z then
- -- Handle Vector objects
- print("[ENTITY INSPECTOR] " .. method .. "(): Vector(" .. result.x .. ", " .. result.y .. ", " ..
- result.z .. ")")
- else
- print("[ENTITY INSPECTOR] " .. method .. "(): " .. tostring(result))
- end
- else
- print("[ENTITY INSPECTOR] " .. method .. "(): Error - " .. tostring(result))
- end
- else
- print("[ENTITY INSPECTOR] " .. method .. ": Not available")
- end
- end
- -- Try to get all key values if available
- print("[ENTITY INSPECTOR] Trying to get all key values:")
- local commonKeys = {"targetname", "classname", "model", "origin", "name", "hammerid", "checkpoint_number"}
- for _, key in ipairs(commonKeys) do
- local success, result = pcall(function()
- if entity.GetKeyValue then
- return entity:GetKeyValue(key)
- else
- return nil
- end
- end)
- if success and result then
- print("[ENTITY INSPECTOR] KeyValue " .. key .. ": " .. tostring(result))
- end
- end
- -- Look for custom properties that might contain checkpoint info
- print("[ENTITY INSPECTOR] Looking for custom properties:")
- local customProps = {"m_checkpoint", "checkpoint", "checkpoint_id", "checkpoint_number", "cp_number"}
- for _, prop in ipairs(customProps) do
- local success, result = pcall(function()
- return entity[prop]
- end)
- if success and result then
- print("[ENTITY INSPECTOR] Custom property " .. prop .. ": " .. tostring(result))
- end
- end
- -- Try to get script scope if available
- if entity.GetScriptScope then
- local scope = entity:GetScriptScope()
- if scope then
- print("[ENTITY INSPECTOR] Script scope found, printing keys:")
- for k, v in pairs(scope) do
- print("[ENTITY INSPECTOR] Script scope key: " .. k .. " = " .. tostring(v))
- end
- else
- print("[ENTITY INSPECTOR] No script scope found")
- end
- end
- -- Check if we can use the entity index to determine the checkpoint number
- if entity.entindex then
- local entIndex = entity:entindex()
- print("[ENTITY INSPECTOR] Entity index: " .. entIndex)
- print("[ENTITY INSPECTOR] This might be useful to map to a checkpoint number")
- end
- print("[ENTITY INSPECTOR] Entity inspection complete")
- end
Advertisement
Add Comment
Please, Sign In to add comment