GameRules.thisunitlist = {
[1] = {name = "basic_unit_melee_1", count = 3},
[2] = {name = "basic_unit_melee_2", count = 0},
[3] = {name = "basic_unit_melee_3", count = 0},
[4] = {name = "basic_unit_melee_4", count = 0},
[5] = {name = "basic_unit_melee_5", count = 0},
[6] = {name = "basic_unit_melee_6", count = 0},
[7] = {name = "basic_unit_melee_7", count = 0},
[8] = {name = "basic_unit_range_1", count = 1},
[9] = {name = "basic_unit_range_2", count = 0},
[10] = {name = "basic_unit_range_3", count = 0},
[11] = {name = "basic_unit_range_4", count = 0},
[12] = {name = "basic_unit_range_5", count = 0},
[13] = {name = "basic_unit_range_6", count = 0},
[14] = {name = "basic_unit_range_7", count = 0},
[15] = {name = "basic_unit_special_1", count = 0},
[16] = {name = "basic_unit_special_2", count = 0},
[17] = {name = "basic_unit_special_3", count = 0},
[18] = {name = "basic_unit_special_4", count = 0},
[19] = {name = "basic_unit_special_5", count = 0},
[20] = {name = "boss_unit_doom", count = 0},
}
function GameMode:OnHeroInGame(hero)
hero.unitlist = deepcopy(GameRules.thisunitlist)
hero.income = 1
end
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if hero:GetGold() >= event.cost then
hero.income = hero.income + event.income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, event.cost, 1)
DeepPrintTable(event)
end
end
function GameMode:OnGameInProgress() -- Функция начнет выполняться, когда начнется матч( на часах будет 00:00 ).
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:IsValidPlayerID(playerID) then
local team = PlayerResource:GetTeam(playerID)
keepers = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(keepers) do
--local hero = PlayerResource:GetSelectedHeroEntity(playerID)
--unit:SetOwner(hero)
unit:SetControllableByPlayer(playerID, true)
end
end
end
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
for key,unit in pairs(hero.unitlist) do
if unit.count > 0 then
spawnCreep(unit.name, unit.count, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
Msg(hero:GetTeam() .. " - Spawned Creep - " .. unit.name .. " - Count: ".. unit.count .. "\n");
end
end
end
return ROUND_DELAY
end)
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), INCOME_COUNT*hero.income, false, 1)
end
return INCOME_DELAY
end)
end
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:172: attempt to perform arithmetic on field 'income' (a nil value)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function '__mul'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:172: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:168>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:158: bad argument #1 to 'pairs' (table expected, got nil)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function <scripts\vscripts\libraries\timers.lua:136>
[C]: in function 'pairs'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:158: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:154>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
hero.income = hero.income + event.income
-- This is the entry-point to your game mode and should be used primarily to precache models/particles/sounds/etc
require('internal/util')
require('gamemode')
keyvalue = {}
GameRules.unitdata = {}
GameRules.thisunitlist = {
[1] = {name = "basic_unit_melee_1", count = 3},
[2] = {name = "basic_unit_melee_2", count = 0},
[3] = {name = "basic_unit_melee_3", count = 0},
[4] = {name = "basic_unit_melee_4", count = 0},
[5] = {name = "basic_unit_melee_5", count = 0},
[6] = {name = "basic_unit_melee_6", count = 0},
[7] = {name = "basic_unit_melee_7", count = 0},
[8] = {name = "basic_unit_range_1", count = 1},
[9] = {name = "basic_unit_range_2", count = 0},
[10] = {name = "basic_unit_range_3", count = 0},
[11] = {name = "basic_unit_range_4", count = 0},
[12] = {name = "basic_unit_range_5", count = 0},
[13] = {name = "basic_unit_range_6", count = 0},
[14] = {name = "basic_unit_range_7", count = 0},
[15] = {name = "basic_unit_special_1", count = 0},
[16] = {name = "basic_unit_special_2", count = 0},
[17] = {name = "basic_unit_special_3", count = 0},
[18] = {name = "basic_unit_special_4", count = 0},
[19] = {name = "basic_unit_special_5", count = 0},
[20] = {name = "boss_unit_doom", count = 0},
}
function spawnCreep(unit, count, start_point, target_point, team)
for i=1, count do
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
end
function spawnOneCreep(unit, start_point, target_point, team)
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
function GameMode:UnitPanelDebug(data)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(data.PlayerID), "load_allunits", GameRules.unitdata )
Msg("Unitpanel debug has called;")
end
function GameMode:OnAllPlayersLoaded()
CustomGameEventManager:RegisterListener( "buy_unit", Dynamic_Wrap(GameMode, "OnBuyUnit") )
CustomGameEventManager:RegisterListener( "unitpanel_debug", Dynamic_Wrap(GameMode, "UnitPanelDebug") )
keyvalue = LoadKeyValues("scripts/npc/npc_units_custom.txt")
Msg("Keyvalues loaded;")
for a, unit in pairs(GameRules.thisunitlist) do
GameRules.unitdata[unit.name] = {ancient = keyvalue[unit.name].AncientUnit, unitclass = keyvalue[unit.name].UnitClass, cost = keyvalue[unit.name].UnitCost, income = keyvalue[unit.name].UnitIncome, health = keyvalue[unit.name].StatusHealth, page = keyvalue[unit.name].UnitPage, mindamage = keyvalue[unit.name].AttackDamageMin, maxdamage = keyvalue[unit.name].AttackDamageMax, attackrange = keyvalue[unit.name].AttackRange, armor = keyvalue[unit.name].ArmorPhysical, ability1 = keyvalue[unit.name].Ability1, ability2 = keyvalue[unit.name].Ability2, ability3 = keyvalue[unit.name].Ability3, ability4 = keyvalue[unit.name].Ability4}
end
Msg("GameRules.unitdata loaded;")
Timers:CreateTimer(0.15, function()
--CCustomGameEventManager::ScriptSend_ServerToPlayer - Invalid player
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:GetConnectionState(playerID) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(playerID) then
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(playerID), "player_think", PlayerResource:GetSelectedHeroEntity(playerID) )
end
end
return 0.15
end)
for team = 2, DOTA_TEAM_COUNT do
if team ~= DOTA_TEAM_NEUTRALS and team ~= DOTA_TEAM_NOTEAM and team < 12 then
local count = PlayerResource:GetPlayerCountForTeam(team)
if count == 0 then
local unitlist = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(unitlist) do
unit:ForceKill(false)
end
end
end
end
end
function GameMode:OnHeroInGame(hero)
hero.unitlist = deepcopy(GameRules.thisunitlist)
hero.income = 1
CustomGameEventManager:Send_ServerToAllClients("load_allunits", GameRules.unitdata )
Msg("load_allunits event started;")
--DeepPrintTable(GameRules.unitdata)
--if PlayerResource:IsValidPlayer(hero:GetPlayerOwnerID()) then
-- CustomGameEventManager:Send_ServerToPlayer( hero:GetPlayerOwner(), "load_allunits", GameRules.unitdata )
--end
end
function deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, _copy(getmetatable(object)))
end
return _copy(object)
end
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if hero:GetGold() >= event.cost then
hero.income = hero.income + event.income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, event.cost, 1)
DeepPrintTable(event)
end
--DeepPrintTable(hero.unitlist)
--GameRules:SendCustomMessage("<font color='#58ACFA'>Игрок купил юнит " .. event.name .. " !</font>", 0, 0)
end
function GameMode:OnGameInProgress() -- Функция начнет выполняться, когда начнется матч( на часах будет 00:00 ).
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:IsValidPlayerID(playerID) then
local team = PlayerResource:GetTeam(playerID)
keepers = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(keepers) do
--local hero = PlayerResource:GetSelectedHeroEntity(playerID)
--unit:SetOwner(hero)
unit:SetControllableByPlayer(playerID, true)
end
end
end
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
for key,unit in pairs(hero.unitlist) do
if unit.count > 0 then
spawnCreep(unit.name, unit.count, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
Msg(hero:GetTeam() .. " - Spawned Creep - " .. unit.name .. " - Count: ".. unit.count .. "\n");
end
end
end
return ROUND_DELAY
end)
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), INCOME_COUNT*hero.income, false, 1)
end
return INCOME_DELAY
end)
end
function Precache( context )
-- Entire heroes (sound effects/voice/models/particles) can be precached with PrecacheUnitByNameSync
-- Custom units from npc_units_custom.txt can also have all of their abilities and precache{} blocks precached in this way
PrecacheUnitByNameSync("npc_dota_hero_dragon_knight", context)
PrecacheUnitByNameSync("npc_dota_hero_sniper", context)
PrecacheUnitByNameSync("npc_dota_hero_vengefulspirit", context)
PrecacheUnitByNameSync("npc_dota_hero_treant", context)
PrecacheUnitByNameSync("npc_dota_hero_omniknight", context)
PrecacheUnitByNameSync("npc_dota_hero_doom_bringer", context)
end
-- Create the game mode when we activate
function Activate()
GameRules.GameMode = GameMode()
GameRules.GameMode:_InitGameMode()
end
$.Msg("JAVASCRIPT SUCCESFULLY LOADED!");
var unitConf = {
};
const maxPages = 4;
var currentPage = 1;
function SelectPage(value)
{
if(currentPage + value > 0 && currentPage + value <= maxPages)
{
currentPage += value;
}
else if(currentPage + value == 0) currentPage = maxPages;
else currentPage = 1;
Game.EmitSound("ui.shortwhoosh");
$('#PageLabelNumber').text = currentPage;
}
function OnPlayerThink( event_data )
{
//$.Msg(unitConf['boss_unit_doom']);
if(Object.keys(unitConf).length == 0)
{
GameEvents.SendCustomGameEventToServer( "unitpanel_debug", {thisdata : 1} );
//$.Msg(unitConf);
}
$('#income-label').GetChild(1).text = event_data.income*10;
for(var i in unitConf)
{
if(currentPage == unitConf[i].page)
{
$(unitConf[i].unitclass).style.visibility = "visible";
}
else $(unitConf[i].unitclass).style.visibility = "collapse";
if(Players.GetGold(Players.GetLocalPlayer()) < unitConf[i].cost)
{
$(unitConf[i].unitclass).style.border = "5px solid #9b0000";
}
else
{
$(unitConf[i].unitclass).style.border = "5px solid #199900";
//Game.EmitSound("Quickbuy.Available");
}
}
/*if(Players.GetGold(Players.GetLocalPlayer()) < 1000)
{
$("#unit_dragon_knight").style.backgroundColor = "red";
$("#unit_sniper").style.backgroundColor = "red";
//$.Msg("NOT ENOUGH MONEY!");
}
else
{
$("#unit_dragon_knight").style.backgroundColor = "none";
$("#unit_sniper").style.backgroundColor = "none";
}*/
}
function OnAllUnitsLoad( event_data )
{
unitConf = event_data;
for(var i in unitConf)
{
(function() {
var m = i;
var thisclass = $(unitConf[m].unitclass);
thisclass.GetChild(1).text = unitConf[m].cost;
var thislocal = $.Localize("#Game_tooltip_income")
+unitConf[m].income*10
+"<br>"+$.Localize("tooltip_"+m)+"<br>"
+"<br>"+$.Localize("Game_tooltip_health")+"<font color='#ffee00'>"+unitConf[m].health+"</font>"
+"<br>"+$.Localize("Game_tooltip_attackrange")+"<font color='#ffee00'>"+unitConf[m].attackrange+"</font>"
+"<br>"+$.Localize("Game_tooltip_damage")+"<font color='#ffee00'>"+unitConf[m].mindamage+"-"+unitConf[m].maxdamage+"</font>"
+"<br>"+$.Localize("Game_tooltip_armor")+"<font color='#ffee00'>"+unitConf[m].armor+"</font>";
if(unitConf[m].ancient == 1) thislocal = $.Localize("#Game_tooltip_ancient") + thislocal;
if(unitConf[m].ability1 != "")
{
thislocal = thislocal+"<br>"+$.Localize("Game_tooltip_ability") +"<font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability1)+"</font>";
if(unitConf[m].ability2 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability2)+"</font>";
if(unitConf[m].ability3 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability3)+"</font>";
if(unitConf[m].ability4 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability4)+"</font>";
}
}
}
}
thisclass.SetPanelEvent("onmouseover", function(){ $.DispatchEvent("DOTAShowTextTooltip", thisclass, thislocal);});
thisclass.SetPanelEvent("onmouseout", function(){ $.DispatchEvent("DOTAHideTextTooltip", thisclass);});
})();
}
}
GameEvents.Subscribe( "player_think", OnPlayerThink);
GameEvents.Subscribe( "load_allunits", OnAllUnitsLoad);
function cmdBuyUnit(unitname, count)
{
$.Msg( "EVENT: unit_buy - true ");
if(Players.GetGold(Players.GetLocalPlayer()) >= unitConf[unitname].cost)
{
var data = {
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
};
GameEvents.SendCustomGameEventToServer( "buy_unit", data );
$.Msg( "EVENT: unit_buy_success - true ");
Game.EmitSound("General.Buy");
}
else
{
Game.EmitSound("General.NoGold");
}
}
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(playerID), "player_think", PlayerResource:GetSelectedHeroEntity(playerID) )
В общем, проблема такова, периодически обнуляются данные, которые записываются в hero.
Решил, что раз playerid обнуляется при отключении, а hero остаётся, то это хорошая возможность хранить индивидуальные данные, но этот подводный камень не даёт мне покоя.
Не могу понять, почему это происходит, какова причина.
P.S. игра идёт нормально, всё работает, но иногда случается так, что данные обнуляются, что портит игру. Когда и из-за чего это происходит понять не могу.
-- This is the entry-point to your game mode and should be used primarily to precache models/particles/sounds/etc
require('internal/util')
require('gamemode')
keyvalue = {}
GameRules.unitdata = {}
GameRules.thisunitlist = {
{name = "basic_unit_melee_1", count = 3},
{name = "basic_unit_melee_2", count = 0},
{name = "basic_unit_melee_3", count = 0},
{name = "basic_unit_melee_4", count = 0},
{name = "basic_unit_melee_5", count = 0},
{name = "basic_unit_melee_6", count = 0},
{name = "basic_unit_melee_7", count = 0},
{name = "basic_unit_range_1", count = 1},
{name = "basic_unit_range_2", count = 0},
{name = "basic_unit_range_3", count = 0},
{name = "basic_unit_range_4", count = 0},
{name = "basic_unit_range_5", count = 0},
{name = "basic_unit_range_6", count = 0},
{name = "basic_unit_range_7", count = 0},
{name = "basic_unit_special_1", count = 0},
{name = "basic_unit_special_2", count = 0},
{name = "basic_unit_special_3", count = 0},
{name = "basic_unit_special_4", count = 0},
{name = "basic_unit_special_5", count = 0},
{name = "boss_unit_doom", count = 0},
}
function spawnCreep(unit, count, start_point, target_point, team)
for i=1, count do
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
end
function spawnOneCreep(unit, start_point, target_point, team)
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
function GameMode:UnitPanelDebug(data)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(data.PlayerID), "load_allunits", GameRules.unitdata )
Msg("Unitpanel debug has called;")
end
function GameMode:OnAllPlayersLoaded()
CustomGameEventManager:RegisterListener( "buy_unit", Dynamic_Wrap(GameMode, "OnBuyUnit") )
CustomGameEventManager:RegisterListener( "sell_unit", Dynamic_Wrap(GameMode, "OnSellUnit") )
CustomGameEventManager:RegisterListener( "unitpanel_debug", Dynamic_Wrap(GameMode, "UnitPanelDebug") )
keyvalue = LoadKeyValues("scripts/npc/npc_units_custom.txt")
Msg("Keyvalues loaded;")
for a, unit in pairs(GameRules.thisunitlist) do
GameRules.unitdata[unit.name] = {ancient = keyvalue[unit.name].AncientUnit, unitclass = keyvalue[unit.name].UnitClass, cost = keyvalue[unit.name].UnitCost, income = keyvalue[unit.name].UnitIncome, health = keyvalue[unit.name].StatusHealth, page = keyvalue[unit.name].UnitPage, mindamage = keyvalue[unit.name].AttackDamageMin, maxdamage = keyvalue[unit.name].AttackDamageMax, attackrange = keyvalue[unit.name].AttackRange, armor = keyvalue[unit.name].ArmorPhysical, ability1 = keyvalue[unit.name].Ability1, ability2 = keyvalue[unit.name].Ability2, ability3 = keyvalue[unit.name].Ability3, ability4 = keyvalue[unit.name].Ability4}
end
Msg("GameRules.unitdata loaded;")
for team = 2, DOTA_TEAM_COUNT do
if team ~= DOTA_TEAM_NEUTRALS and team ~= DOTA_TEAM_NOTEAM and team < 12 then
local count = PlayerResource:GetPlayerCountForTeam(team)
if count == 0 then
local unitlist = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(unitlist) do
unit:ForceKill(false)
end
end
end
end
end
function GameMode:OnHeroInGame(hero)
hero.unitlist = deepcopy(GameRules.thisunitlist)
hero.income = 1
CustomGameEventManager:Send_ServerToAllClients("load_allunits", GameRules.unitdata )
Msg("load_allunits event started;")
--Timers:CreateTimer(0.15, function()
--CCustomGameEventManager::ScriptSend_ServerToPlayer - Invalid player
--local owner = hero:GetPlayerOwner()
-- local ownerid = hero:GetPlayerOwnerID()
-- if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
-- CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "player_think", {income = hero.income} )
-- end
-- return 0.15
--end)
local ownerid = hero:GetPlayerOwnerID()
if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "load_playerunits", hero.unitlist )
end
--DeepPrintTable(GameRules.unitdata)
--if PlayerResource:IsValidPlayer(hero:GetPlayerOwnerID()) then
-- CustomGameEventManager:Send_ServerToPlayer( hero:GetPlayerOwner(), "load_allunits", GameRules.unitdata )
--end
end
function deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, _copy(getmetatable(object)))
end
return _copy(object)
end
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if event.income ~= nil and event.count ~= nil and event.cost ~= nil then
if hero:GetGold() >= event.cost then
hero.income = hero.income + event.income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, event.cost, 1)
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
--DeepPrintTable(hero.unitlist)
--GameRules:SendCustomMessage("<font color='#58ACFA'>Игрок купил юнит " .. event.name .. " !</font>", 0, 0)
end
function GameMode:OnSellUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
local unitcount = 0;
local istrue = true
if event.income ~= nil and event.count ~= nil then
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
if unit.count == 0 then
istrue = false
break
end
end
if unit.count > 0 then unitcount = unitcount + unit.count end
end
if istrue == true then
if unitcount > 4 then
hero.income = hero.income - event.income
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), event.cost, false, 1)
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count - event.count
break
end
end
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
end
end
function GameMode:OnGameInProgress() -- Функция начнет выполняться, когда начнется матч( на часах будет 00:00 ).
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:IsValidPlayerID(playerID) then
local team = PlayerResource:GetTeam(playerID)
keepers = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(keepers) do
--local hero = PlayerResource:GetSelectedHeroEntity(playerID)
--unit:SetOwner(hero)
unit:SetControllableByPlayer(playerID, true)
unit:SetOwner(PlayerResource:GetPlayer(playerID))
end
end
end
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
for key,unit in pairs(hero.unitlist) do
if unit.count > 0 then
spawnCreep(unit.name, unit.count, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
Msg(hero:GetTeam() .. " - Spawned Creep - " .. unit.name .. " - Count: ".. unit.count .. "\n");
end
end
end
return ROUND_DELAY
end)
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), INCOME_COUNT*hero.income, false, 1)
end
return INCOME_DELAY
end)
end
function Precache( context )
-- Entire heroes (sound effects/voice/models/particles) can be precached with PrecacheUnitByNameSync
-- Custom units from npc_units_custom.txt can also have all of their abilities and precache{} blocks precached in this way
PrecacheUnitByNameSync("npc_dota_hero_dragon_knight", context)
PrecacheUnitByNameSync("npc_dota_hero_sniper", context)
PrecacheUnitByNameSync("npc_dota_hero_vengefulspirit", context)
PrecacheUnitByNameSync("npc_dota_hero_treant", context)
PrecacheUnitByNameSync("npc_dota_hero_omniknight", context)
PrecacheUnitByNameSync("npc_dota_hero_doom_bringer", context)
PrecacheUnitByNameSync("npc_dota_Hero_crystal_maiden", context)
end
-- Create the game mode when we activate
function Activate()
GameRules.GameMode = GameMode()
GameRules.GameMode:_InitGameMode()
end
$.Msg("JAVASCRIPT SUCCESFULLY LOADED!");
var unitConf = {};
var unitHaved = {};
const maxPages = 4;
var currentPage = 1;
var myincome = 1;
//Runs a function periodically
//start - how much of an additional delay to have (on top of the tick refresh) (set this to -1 to run the function immediately
//time - how long to run for. set this to -1 to run infinitely
//tick - how many seconds to elapse between ticks (assumes time / tick is an integer) (set this to negative to run a set amount of ticks, e.g. -30 will run 30 ticks in whatever time period given)
//func - func to run (return true to cancel)
//UPDATE June 29 2015 - fixed some enclosure issues, added a safecheck for time overflow
$.Every = function(start, time, tick, func){
var startTime = Game.Time();
var tickRate = tick;
if(tick < 1){
if(start < 0) tick--;
tickRate = time / -tick;
}
var tickCount = time/ tickRate;
if(time < 0){
tickCount = 9999999;
}
var numRan = 0;
$.Schedule(start, (function(start,numRan,tickRate,tickCount){
return function(){
if(start < 0){
start = 0;
if(func()){
return;
};
}
var tickNew = function(){
numRan++;
delay = (startTime+tickRate*numRan)-Game.Time();
/* if((startTime+tickRate*numRan)-Game.Time() < 0){
$.Msg('[ERROR] Function ' + func + ' taking too long to loop!')
delay = 0;
}*/
$.Schedule(delay, function(){
if(func()){
return;
};
tickCount--;
if(tickCount > 0) tickNew();
});
};
tickNew();
}
})(start,numRan,tickRate,tickCount));
};
$.Every(0, -1, -10, function(){
onJavaTimerTick();
});
function OnUnitBuySuccess(data)
{
myincome = data.income;
//$.Msg(data);
}
function onJavaTimerTick( )
{
if(Object.keys(unitConf).length == 0)
{
GameEvents.SendCustomGameEventToServer( "unitpanel_debug", {thisdata : 1} );
//$.Msg(unitConf);
}
$('#income-label').GetChild(1).text = myincome*10;
for(var i in unitConf)
{
if(currentPage == unitConf[i].page)
{
$(unitConf[i].unitclass).style.visibility = "visible";
}
else $(unitConf[i].unitclass).style.visibility = "collapse";
if(Players.GetGold(Players.GetLocalPlayer()) < unitConf[i].cost)
{
$(unitConf[i].unitclass).style.border = "5px solid #9b0000";
}
else
{
$(unitConf[i].unitclass).style.border = "5px solid #199900";
//Game.EmitSound("Quickbuy.Available");
}
}
}
function SelectPage(value)
{
if(currentPage + value > 0 && currentPage + value <= maxPages)
{
currentPage += value;
}
else if(currentPage + value == 0) currentPage = maxPages;
else currentPage = 1;
Game.EmitSound("ui.shortwhoosh");
$('#PageLabelNumber').text = currentPage;
}
function OnAllUnitsLoad( event_data )
{
unitConf = event_data;
for(var i in unitConf)
{
(function() {
var m = i;
var thisclass = $(unitConf[m].unitclass);
thisclass.GetChild(1).text = unitConf[m].cost;
var thislocal = $.Localize("#Game_tooltip_income")
+unitConf[m].income*10
+"<br>"+$.Localize("tooltip_"+m)+"<br>"
+"<br>"+$.Localize("Game_tooltip_health")+"<font color='#ffee00'>"+unitConf[m].health+"</font>"
+"<br>"+$.Localize("Game_tooltip_attackrange")+"<font color='#ffee00'>"+unitConf[m].attackrange+"</font>"
+"<br>"+$.Localize("Game_tooltip_damage")+"<font color='#ffee00'>"+unitConf[m].mindamage+"-"+unitConf[m].maxdamage+"</font>"
+"<br>"+$.Localize("Game_tooltip_armor")+"<font color='#ffee00'>"+unitConf[m].armor+"</font>";
if(unitConf[m].ancient == 1) thislocal = $.Localize("#Game_tooltip_ancient") + thislocal;
if(unitConf[m].ability1 != "")
{
thislocal = thislocal+"<br>"+$.Localize("Game_tooltip_ability") +"<font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability1)+"</font>";
if(unitConf[m].ability2 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability2)+"</font>";
if(unitConf[m].ability3 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability3)+"</font>";
if(unitConf[m].ability4 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability4)+"</font>";
}
}
}
}
thisclass.SetPanelEvent("onmouseover", function(){ $.DispatchEvent("DOTAShowTextTooltip", thisclass, thislocal);});
thisclass.SetPanelEvent("onmouseout", function(){ $.DispatchEvent("DOTAHideTextTooltip", thisclass);});
})();
}
}
function OnPlayerUnitsLoad(data)
{
//$.Msg(data);
var newunits = {};
for(var i in data)
{
(function() {
var m = i;
var name = data[m].name
newunits[name] = {count: data[m].count, unitclass: "unitclass_"+name}
})();
}
ReloadCurrentUnitsPanel(newunits);
}
function ReloadCurrentUnitsPanel(units)
{
var unitlistlabel = $('#unitlist-label');
unitlistlabel.RemoveAndDeleteChildren();
delete unitHaved;
unitHaved = units;
for(i in unitHaved)
{
(function() {
var m = i;
if(unitHaved[m].count > 0)
{
var thispanel = $.CreatePanel("Button", unitlistlabel, unitHaved[m].unitclass );
var thislabel = $.CreatePanel("Label", thispanel, "label_"+unitHaved[m].unitclass);
thispanel.SetPanelEvent( 'onactivate', function(){ cmdSellUnit(m, 1);});
thispanel.AddClass("currentunit_list");
thislabel.AddClass("currentunit_list_label");
thispanel.style.border = "2px solid white";
thislabel.text = "$";
thislabel.style.visibility = "collapse";
thispanel.SetPanelEvent("onmouseover", function(){
thislabel.style.visibility = "visible";
thispanel.style.border = "3px solid yellow";
$.DispatchEvent("DOTAShowTextTooltip", thispanel, $.Localize("#Game_tooltip_sellunit")+$.Localize("#tooltip_"+m)+"<br>"+ $.Localize("#Game_tooltip_currentunitcount") + unitHaved[m].count);
});
thispanel.SetPanelEvent("onmouseout", function(){
thislabel.style.visibility = "collapse";
thispanel.style.border = "2px solid white";
$.DispatchEvent("DOTAHideTextTooltip", thispanel);
});
thispanel.style.backgroundSize = "100% 100%";
thispanel.style.backgroundImage = "url('file://{images}/custom_game/avatar_"+m+".png')";
}
})();
}
}
function cmdSellUnit(unitname, count)
{
if(unitHaved[unitname].count > 0)
{
$.Msg( "EVENT: unit_sell - true ");
var unitcount = 0;
for(var i in unitHaved)
{
(function(){
var m = i;
if(unitHaved[m].count > 0) unitcount += unitHaved[m].count;
//$.Msg(unitcount);
})();
}
if(unitcount > 4)
{
var data = {
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
};
GameEvents.SendCustomGameEventToServer( "sell_unit", data );
$.Msg( "EVENT: unit_sell_success - true ");
Game.EmitSound("General.Sell");
}
else
{
Game.EmitSound("General.NoGold");
}
}
}
GameEvents.Subscribe( "unitbuy_success", OnUnitBuySuccess);
GameEvents.Subscribe( "load_allunits", OnAllUnitsLoad);
GameEvents.Subscribe( "load_playerunits", OnPlayerUnitsLoad);
function cmdBuyUnit(unitname, count)
{
$.Msg( "EVENT: unit_buy - true ");
if(Players.GetGold(Players.GetLocalPlayer()) >= unitConf[unitname].cost)
{
var data = {
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
};
GameEvents.SendCustomGameEventToServer( "buy_unit", data );
$.Msg( "EVENT: unit_buy_success - true ");
Game.EmitSound("General.Buy");
}
else
{
Game.EmitSound("General.NoGold");
}
}
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: attempt to perform arithmetic on field 'income' (a nil value)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function '__mul'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:219>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
10 - Spawned Creep - basic_unit_melee_1 - Count: 3
10 - Spawned Creep - basic_unit_range_1 - Count: 2
6 - Spawned Creep - basic_unit_melee_1 - Count: 5
2 - Spawned Creep - basic_unit_melee_1 - Count: 4
2 - Spawned Creep - basic_unit_range_1 - Count: 1
8 - Spawned Creep - basic_unit_melee_1 - Count: 3
8 - Spawned Creep - basic_unit_range_1 - Count: 1
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: bad argument #1 to 'pairs' (table expected, got nil)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function <scripts\vscripts\libraries\timers.lua:136>
[C]: in function 'pairs'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:205>
[C]: in function 'xpcall'
-- This is the entry-point to your game mode and should be used primarily to precache models/particles/sounds/etc
require('internal/util')
require('gamemode')
keyvalue = {}
GameRules.unitdata = {}
GameRules.thisunitlist = {
{name = "basic_unit_melee_1", count = 3},
{name = "basic_unit_melee_2", count = 0},
{name = "basic_unit_melee_3", count = 0},
{name = "basic_unit_melee_4", count = 0},
{name = "basic_unit_melee_5", count = 0},
{name = "basic_unit_melee_6", count = 0},
{name = "basic_unit_melee_7", count = 0},
{name = "basic_unit_range_1", count = 1},
{name = "basic_unit_range_2", count = 0},
{name = "basic_unit_range_3", count = 0},
{name = "basic_unit_range_4", count = 0},
{name = "basic_unit_range_5", count = 0},
{name = "basic_unit_range_6", count = 0},
{name = "basic_unit_range_7", count = 0},
{name = "basic_unit_special_1", count = 0},
{name = "basic_unit_special_2", count = 0},
{name = "basic_unit_special_3", count = 0},
{name = "basic_unit_special_4", count = 0},
{name = "basic_unit_special_5", count = 0},
{name = "boss_unit_doom", count = 0},
}
function spawnCreep(unit, count, start_point, target_point, team)
for i=1, count do
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
end
function spawnOneCreep(unit, start_point, target_point, team)
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
function GameMode:UnitPanelDebug(data)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(data.PlayerID), "load_allunits", GameRules.unitdata )
Msg("Unitpanel debug has called;")
end
function GameMode:OnAllPlayersLoaded()
CustomGameEventManager:RegisterListener( "buy_unit", Dynamic_Wrap(GameMode, "OnBuyUnit") )
CustomGameEventManager:RegisterListener( "sell_unit", Dynamic_Wrap(GameMode, "OnSellUnit") )
CustomGameEventManager:RegisterListener( "unitpanel_debug", Dynamic_Wrap(GameMode, "UnitPanelDebug") )
keyvalue = LoadKeyValues("scripts/npc/npc_units_custom.txt")
Msg("Keyvalues loaded;")
for a, unit in pairs(GameRules.thisunitlist) do
GameRules.unitdata[unit.name] = {ancient = keyvalue[unit.name].AncientUnit, unitclass = keyvalue[unit.name].UnitClass, cost = keyvalue[unit.name].UnitCost, income = keyvalue[unit.name].UnitIncome, health = keyvalue[unit.name].StatusHealth, page = keyvalue[unit.name].UnitPage, mindamage = keyvalue[unit.name].AttackDamageMin, maxdamage = keyvalue[unit.name].AttackDamageMax, attackrange = keyvalue[unit.name].AttackRange, armor = keyvalue[unit.name].ArmorPhysical, ability1 = keyvalue[unit.name].Ability1, ability2 = keyvalue[unit.name].Ability2, ability3 = keyvalue[unit.name].Ability3, ability4 = keyvalue[unit.name].Ability4}
end
Msg("GameRules.unitdata loaded;")
for team = 2, DOTA_TEAM_COUNT do
if team ~= DOTA_TEAM_NEUTRALS and team ~= DOTA_TEAM_NOTEAM and team < 12 then
local count = PlayerResource:GetPlayerCountForTeam(team)
if count == 0 then
local unitlist = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(unitlist) do
unit:ForceKill(false)
end
end
end
end
end
function GameMode:OnHeroInGame(hero)
hero.unitlist = deepcopy(GameRules.thisunitlist)
hero.income = 1
CustomGameEventManager:Send_ServerToAllClients("load_allunits", GameRules.unitdata )
Msg("load_allunits event started;")
--Timers:CreateTimer(0.15, function()
--CCustomGameEventManager::ScriptSend_ServerToPlayer - Invalid player
--local owner = hero:GetPlayerOwner()
-- local ownerid = hero:GetPlayerOwnerID()
-- if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
-- CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "player_think", {income = hero.income} )
-- end
-- return 0.15
--end)
local ownerid = hero:GetPlayerOwnerID()
if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "load_playerunits", hero.unitlist )
end
--DeepPrintTable(GameRules.unitdata)
--if PlayerResource:IsValidPlayer(hero:GetPlayerOwnerID()) then
-- CustomGameEventManager:Send_ServerToPlayer( hero:GetPlayerOwner(), "load_allunits", GameRules.unitdata )
--end
end
function deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, _copy(getmetatable(object)))
end
return _copy(object)
end
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if event.income ~= nil and event.count ~= nil and event.cost ~= nil then
if hero:GetGold() >= event.cost then
hero.income = hero.income + event.income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, event.cost, 1)
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
--DeepPrintTable(hero.unitlist)
--GameRules:SendCustomMessage("<font color='#58ACFA'>Игрок купил юнит " .. event.name .. " !</font>", 0, 0)
end
function GameMode:OnSellUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
local unitcount = 0;
local istrue = true
if event.income ~= nil and event.count ~= nil then
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
if unit.count == 0 then
istrue = false
break
end
end
if unit.count > 0 then unitcount = unitcount + unit.count end
end
if istrue == true then
if unitcount > 4 then
hero.income = hero.income - event.income
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), event.cost, false, 1)
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count - event.count
break
end
end
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
end
end
function GameMode:OnGameInProgress() -- Функция начнет выполняться, когда начнется матч( на часах будет 00:00 ).
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:IsValidPlayerID(playerID) then
local team = PlayerResource:GetTeam(playerID)
keepers = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(keepers) do
--local hero = PlayerResource:GetSelectedHeroEntity(playerID)
--unit:SetOwner(hero)
unit:SetControllableByPlayer(playerID, true)
unit:SetOwner(PlayerResource:GetPlayer(playerID))
end
end
end
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
for key,unit in pairs(hero.unitlist) do
if unit.count > 0 then
spawnCreep(unit.name, unit.count, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
Msg(hero:GetTeam() .. " - Spawned Creep - " .. unit.name .. " - Count: ".. unit.count .. "\n");
end
end
end
return ROUND_DELAY
end)
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), INCOME_COUNT*hero.income, false, 1)
end
return INCOME_DELAY
end)
end
function Precache( context )
-- Entire heroes (sound effects/voice/models/particles) can be precached with PrecacheUnitByNameSync
-- Custom units from npc_units_custom.txt can also have all of their abilities and precache{} blocks precached in this way
PrecacheUnitByNameSync("npc_dota_hero_dragon_knight", context)
PrecacheUnitByNameSync("npc_dota_hero_sniper", context)
PrecacheUnitByNameSync("npc_dota_hero_vengefulspirit", context)
PrecacheUnitByNameSync("npc_dota_hero_treant", context)
PrecacheUnitByNameSync("npc_dota_hero_omniknight", context)
PrecacheUnitByNameSync("npc_dota_hero_doom_bringer", context)
PrecacheUnitByNameSync("npc_dota_Hero_crystal_maiden", context)
end
-- Create the game mode when we activate
function Activate()
GameRules.GameMode = GameMode()
GameRules.GameMode:_InitGameMode()
end
$.Msg("JAVASCRIPT SUCCESFULLY LOADED!");
var unitConf = {};
var unitHaved = {};
const maxPages = 4;
var currentPage = 1;
var myincome = 1;
//Runs a function periodically
//start - how much of an additional delay to have (on top of the tick refresh) (set this to -1 to run the function immediately
//time - how long to run for. set this to -1 to run infinitely
//tick - how many seconds to elapse between ticks (assumes time / tick is an integer) (set this to negative to run a set amount of ticks, e.g. -30 will run 30 ticks in whatever time period given)
//func - func to run (return true to cancel)
//UPDATE June 29 2015 - fixed some enclosure issues, added a safecheck for time overflow
$.Every = function(start, time, tick, func){
var startTime = Game.Time();
var tickRate = tick;
if(tick < 1){
if(start < 0) tick--;
tickRate = time / -tick;
}
var tickCount = time/ tickRate;
if(time < 0){
tickCount = 9999999;
}
var numRan = 0;
$.Schedule(start, (function(start,numRan,tickRate,tickCount){
return function(){
if(start < 0){
start = 0;
if(func()){
return;
};
}
var tickNew = function(){
numRan++;
delay = (startTime+tickRate*numRan)-Game.Time();
/* if((startTime+tickRate*numRan)-Game.Time() < 0){
$.Msg('[ERROR] Function ' + func + ' taking too long to loop!')
delay = 0;
}*/
$.Schedule(delay, function(){
if(func()){
return;
};
tickCount--;
if(tickCount > 0) tickNew();
});
};
tickNew();
}
})(start,numRan,tickRate,tickCount));
};
$.Every(0, -1, -10, function(){
onJavaTimerTick();
});
function OnUnitBuySuccess(data)
{
myincome = data.income;
//$.Msg(data);
}
function onJavaTimerTick( )
{
if(Object.keys(unitConf).length == 0)
{
GameEvents.SendCustomGameEventToServer( "unitpanel_debug", {thisdata : 1} );
//$.Msg(unitConf);
}
$('#income-label').GetChild(1).text = myincome*10;
for(var i in unitConf)
{
if(currentPage == unitConf[i].page)
{
$(unitConf[i].unitclass).style.visibility = "visible";
}
else $(unitConf[i].unitclass).style.visibility = "collapse";
if(Players.GetGold(Players.GetLocalPlayer()) < unitConf[i].cost)
{
$(unitConf[i].unitclass).style.border = "5px solid #9b0000";
}
else
{
$(unitConf[i].unitclass).style.border = "5px solid #199900";
//Game.EmitSound("Quickbuy.Available");
}
}
}
function SelectPage(value)
{
if(currentPage + value > 0 && currentPage + value <= maxPages)
{
currentPage += value;
}
else if(currentPage + value == 0) currentPage = maxPages;
else currentPage = 1;
Game.EmitSound("ui.shortwhoosh");
$('#PageLabelNumber').text = currentPage;
}
function OnAllUnitsLoad( event_data )
{
unitConf = event_data;
for(var i in unitConf)
{
(function() {
var m = i;
var thisclass = $(unitConf[m].unitclass);
thisclass.GetChild(1).text = unitConf[m].cost;
var thislocal = $.Localize("#Game_tooltip_income")
+unitConf[m].income*10
+"<br>"+$.Localize("tooltip_"+m)+"<br>"
+"<br>"+$.Localize("Game_tooltip_health")+"<font color='#ffee00'>"+unitConf[m].health+"</font>"
+"<br>"+$.Localize("Game_tooltip_attackrange")+"<font color='#ffee00'>"+unitConf[m].attackrange+"</font>"
+"<br>"+$.Localize("Game_tooltip_damage")+"<font color='#ffee00'>"+unitConf[m].mindamage+"-"+unitConf[m].maxdamage+"</font>"
+"<br>"+$.Localize("Game_tooltip_armor")+"<font color='#ffee00'>"+unitConf[m].armor+"</font>";
if(unitConf[m].ancient == 1) thislocal = $.Localize("#Game_tooltip_ancient") + thislocal;
if(unitConf[m].ability1 != "")
{
thislocal = thislocal+"<br>"+$.Localize("Game_tooltip_ability") +"<font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability1)+"</font>";
if(unitConf[m].ability2 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability2)+"</font>";
if(unitConf[m].ability3 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability3)+"</font>";
if(unitConf[m].ability4 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability4)+"</font>";
}
}
}
}
thisclass.SetPanelEvent("onmouseover", function(){ $.DispatchEvent("DOTAShowTextTooltip", thisclass, thislocal);});
thisclass.SetPanelEvent("onmouseout", function(){ $.DispatchEvent("DOTAHideTextTooltip", thisclass);});
})();
}
}
function OnPlayerUnitsLoad(data)
{
//$.Msg(data);
var newunits = {};
for(var i in data)
{
(function() {
var m = i;
var name = data[m].name
newunits[name] = {count: data[m].count, unitclass: "unitclass_"+name}
})();
}
ReloadCurrentUnitsPanel(newunits);
}
function ReloadCurrentUnitsPanel(units)
{
var unitlistlabel = $('#unitlist-label');
unitlistlabel.RemoveAndDeleteChildren();
delete unitHaved;
unitHaved = units;
for(i in unitHaved)
{
(function() {
var m = i;
if(unitHaved[m].count > 0)
{
var thispanel = $.CreatePanel("Button", unitlistlabel, unitHaved[m].unitclass );
var thislabel = $.CreatePanel("Label", thispanel, "label_"+unitHaved[m].unitclass);
thispanel.SetPanelEvent( 'onactivate', function(){ cmdSellUnit(m, 1);});
thispanel.AddClass("currentunit_list");
thislabel.AddClass("currentunit_list_label");
thispanel.style.border = "2px solid white";
thislabel.text = "$";
thislabel.style.visibility = "collapse";
thispanel.SetPanelEvent("onmouseover", function(){
thislabel.style.visibility = "visible";
thispanel.style.border = "3px solid yellow";
$.DispatchEvent("DOTAShowTextTooltip", thispanel, $.Localize("#Game_tooltip_sellunit")+$.Localize("#tooltip_"+m)+"<br>"+ $.Localize("#Game_tooltip_currentunitcount") + unitHaved[m].count);
});
thispanel.SetPanelEvent("onmouseout", function(){
thislabel.style.visibility = "collapse";
thispanel.style.border = "2px solid white";
$.DispatchEvent("DOTAHideTextTooltip", thispanel);
});
thispanel.style.backgroundSize = "100% 100%";
thispanel.style.backgroundImage = "url('file://{images}/custom_game/avatar_"+m+".png')";
}
})();
}
}
function cmdSellUnit(unitname, count)
{
if(unitHaved[unitname].count > 0)
{
$.Msg( "EVENT: unit_sell - true ");
var unitcount = 0;
for(var i in unitHaved)
{
(function(){
var m = i;
if(unitHaved[m].count > 0) unitcount += unitHaved[m].count;
//$.Msg(unitcount);
})();
}
if(unitcount > 4)
{
var data = {
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
};
GameEvents.SendCustomGameEventToServer( "sell_unit", data );
$.Msg( "EVENT: unit_sell_success - true ");
Game.EmitSound("General.Sell");
}
else
{
Game.EmitSound("General.NoGold");
}
}
}
GameEvents.Subscribe( "unitbuy_success", OnUnitBuySuccess);
GameEvents.Subscribe( "load_allunits", OnAllUnitsLoad);
GameEvents.Subscribe( "load_playerunits", OnPlayerUnitsLoad);
function cmdBuyUnit(unitname, count)
{
$.Msg( "EVENT: unit_buy - true ");
if(Players.GetGold(Players.GetLocalPlayer()) >= unitConf[unitname].cost)
{
var data = {
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
};
GameEvents.SendCustomGameEventToServer( "buy_unit", data );
$.Msg( "EVENT: unit_buy_success - true ");
Game.EmitSound("General.Buy");
}
else
{
Game.EmitSound("General.NoGold");
}
}
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: attempt to perform arithmetic on field 'income' (a nil value)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function '__mul'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:219>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
10 - Spawned Creep - basic_unit_melee_1 - Count: 3
10 - Spawned Creep - basic_unit_range_1 - Count: 2
6 - Spawned Creep - basic_unit_melee_1 - Count: 5
2 - Spawned Creep - basic_unit_melee_1 - Count: 4
2 - Spawned Creep - basic_unit_range_1 - Count: 1
8 - Spawned Creep - basic_unit_melee_1 - Count: 3
8 - Spawned Creep - basic_unit_range_1 - Count: 1
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: bad argument #1 to 'pairs' (table expected, got nil)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function <scripts\vscripts\libraries\timers.lua:136>
[C]: in function 'pairs'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:205>
[C]: in function 'xpcall'
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: attempt to perform arithmetic on field 'income' (a nil value)
name: unitname,
count: count,
cost: unitConf[unitname].cost,
income: unitConf[unitname].income
CustomGameEventManager:RegisterListener( "buy_unit", Dynamic_Wrap(GameMode, "OnBuyUnit") )
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if event.income ~= nil and event.count ~= nil and event.cost ~= nil then
if hero:GetGold() >= event.cost then
hero.income = hero.income + event.income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, event.cost, 1)
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
--DeepPrintTable(hero.unitlist)
--GameRules:SendCustomMessage("<font color='#58ACFA'>Игрок купил юнит " .. event.name .. " !</font>", 0, 0)
end
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: bad argument #1 to 'pairs' (table expected, got nil)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function <scripts\vscripts\libraries\timers.lua:136>
[C]: in function 'pairs'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:209: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:205>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
[VScript] ...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: attempt to perform arithmetic on field 'income' (a nil value)
stack traceback:
scripts\vscripts\libraries\timers.lua:137: in function '__mul'
...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:223: in function <...94786\943694786.vpk:scripts\vscripts\addon_game_mode.lua:219>
[C]: in function 'xpcall'
scripts\vscripts\libraries\timers.lua:136: in function <scripts\vscripts\libraries\timers.lua:94>
-- This is the entry-point to your game mode and should be used primarily to precache models/particles/sounds/etc
require('internal/util')
require('gamemode')
keyvalue = {}
GameRules.unitdata = {}
GameRules.thisunitlist = {
{name = "basic_unit_melee_1", count = 3},
{name = "basic_unit_melee_2", count = 0},
{name = "basic_unit_melee_3", count = 0},
{name = "basic_unit_melee_4", count = 0},
{name = "basic_unit_melee_5", count = 0},
{name = "basic_unit_melee_6", count = 0},
{name = "basic_unit_melee_7", count = 0},
{name = "basic_unit_range_1", count = 1},
{name = "basic_unit_range_2", count = 0},
{name = "basic_unit_range_3", count = 0},
{name = "basic_unit_range_4", count = 0},
{name = "basic_unit_range_5", count = 0},
{name = "basic_unit_range_6", count = 0},
{name = "basic_unit_range_7", count = 0},
{name = "basic_unit_special_1", count = 0},
{name = "basic_unit_special_2", count = 0},
{name = "basic_unit_special_3", count = 0},
{name = "basic_unit_special_4", count = 0},
{name = "basic_unit_special_5", count = 0},
{name = "boss_unit_doom", count = 0},
}
function spawnCreep(unit, count, start_point, target_point, team)
for i=1, count do
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
end
function spawnOneCreep(unit, start_point, target_point, team)
local r_unit = CreateUnitByName( unit, start_point + RandomVector( RandomFloat( 0, 200 ) ), true, nil, nil, team )
r_unit:SetInitialGoalEntity( target_point )
end
function GameMode:UnitPanelDebug(data)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(data.PlayerID), "load_allunits", GameRules.unitdata )
Msg("Unitpanel debug has called;")
end
function GameMode:OnAllPlayersLoaded()
CustomGameEventManager:RegisterListener( "buy_unit", Dynamic_Wrap(GameMode, "OnBuyUnit") )
CustomGameEventManager:RegisterListener( "sell_unit", Dynamic_Wrap(GameMode, "OnSellUnit") )
CustomGameEventManager:RegisterListener( "unitpanel_debug", Dynamic_Wrap(GameMode, "UnitPanelDebug") )
keyvalue = LoadKeyValues("scripts/npc/npc_units_custom.txt")
Msg("Keyvalues loaded;")
for a, unit in pairs(GameRules.thisunitlist) do
GameRules.unitdata[unit.name] = {ancient = keyvalue[unit.name].AncientUnit, unitclass = keyvalue[unit.name].UnitClass, cost = keyvalue[unit.name].UnitCost, income = keyvalue[unit.name].UnitIncome, health = keyvalue[unit.name].StatusHealth, page = keyvalue[unit.name].UnitPage, mindamage = keyvalue[unit.name].AttackDamageMin, maxdamage = keyvalue[unit.name].AttackDamageMax, attackrange = keyvalue[unit.name].AttackRange, armor = keyvalue[unit.name].ArmorPhysical, ability1 = keyvalue[unit.name].Ability1, ability2 = keyvalue[unit.name].Ability2, ability3 = keyvalue[unit.name].Ability3, ability4 = keyvalue[unit.name].Ability4}
end
Msg("GameRules.unitdata loaded;")
for team = 2, DOTA_TEAM_COUNT do
if team ~= DOTA_TEAM_NEUTRALS and team ~= DOTA_TEAM_NOTEAM and team < 12 then
local count = PlayerResource:GetPlayerCountForTeam(team)
if count == 0 then
local unitlist = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(unitlist) do
unit:ForceKill(false)
end
end
end
end
end
function GameMode:OnHeroInGame(hero)
hero.unitlist = deepcopy(GameRules.thisunitlist)
hero.income = 1
CustomGameEventManager:Send_ServerToAllClients("load_allunits", GameRules.unitdata )
Msg("load_allunits event started;")
--Timers:CreateTimer(0.15, function()
--CCustomGameEventManager::ScriptSend_ServerToPlayer - Invalid player
--local owner = hero:GetPlayerOwner()
-- local ownerid = hero:GetPlayerOwnerID()
-- if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
-- CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "player_think", {income = hero.income} )
-- end
-- return 0.15
--end)
local ownerid = hero:GetPlayerOwnerID()
if PlayerResource:GetConnectionState(ownerid) == DOTA_CONNECTION_STATE_CONNECTED and PlayerResource:IsValidPlayer(ownerid) then
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(ownerid), "load_playerunits", hero.unitlist )
end
--DeepPrintTable(GameRules.unitdata)
--if PlayerResource:IsValidPlayer(hero:GetPlayerOwnerID()) then
-- CustomGameEventManager:Send_ServerToPlayer( hero:GetPlayerOwner(), "load_allunits", GameRules.unitdata )
--end
end
function deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, _copy(getmetatable(object)))
end
return _copy(object)
end
function GameMode:OnBuyUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
if event.count ~= nil then
if hero:GetGold() >= GameRules.unitdata[event.name].cost then
hero.income = hero.income + GameRules.unitdata[event.name].income
if event.count == 0 then
local team = hero:GetTeam()
spawnCreep(event.name, 1, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
else
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count + event.count
break
end
end
end
PlayerResource:SpendGold(event.PlayerID, GameRules.unitdata[event.name].cost, 1)
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
--DeepPrintTable(hero.unitlist)
--GameRules:SendCustomMessage("<font color='#58ACFA'>Игрок купил юнит " .. event.name .. " !</font>", 0, 0)
end
function GameMode:OnSellUnit(event)
local hero = PlayerResource:GetSelectedHeroEntity(event.PlayerID)
local unitcount = 0;
local istrue = true
if event.count ~= nil then
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
if unit.count == 0 then
istrue = false
break
end
end
if unit.count > 0 then unitcount = unitcount + unit.count end
end
if istrue == true then
if unitcount > 4 then
hero.income = hero.income - GameRules.unitdata[event.name].income
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), GameRules.unitdata[event.name].cost, false, 1)
for a, unit in pairs(hero.unitlist) do
if unit.name == event.name then
unit.count = unit.count - event.count
break
end
end
--DeepPrintTable(event)
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "load_playerunits", hero.unitlist )
CustomGameEventManager:Send_ServerToPlayer( PlayerResource:GetPlayer(event.PlayerID), "unitbuy_success", {income = hero.income} )
end
end
end
end
function GameMode:OnGameInProgress() -- Функция начнет выполняться, когда начнется матч( на часах будет 00:00 ).
for playerID = 0, DOTA_MAX_TEAM_PLAYERS-1 do
if PlayerResource:IsValidPlayerID(playerID) then
local team = PlayerResource:GetTeam(playerID)
keepers = FindUnitsInRadius(team, Vector(0, 0, 0), nil, FIND_UNITS_EVERYWHERE, DOTA_UNIT_TARGET_TEAM_FRIENDLY, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
-- Make the found units move to (0, 0, 0)
for _,unit in pairs(keepers) do
--local hero = PlayerResource:GetSelectedHeroEntity(playerID)
--unit:SetOwner(hero)
unit:SetControllableByPlayer(playerID, true)
unit:SetOwner(PlayerResource:GetPlayer(playerID))
end
end
end
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
for key,unit in pairs(hero.unitlist) do
if unit.count > 0 then
spawnCreep(unit.name, unit.count, Entities:FindByName( nil, "spawn_" .. team):GetAbsOrigin(), Entities:FindByName( nil, "point_" .. team), team)
Msg(hero:GetTeam() .. " - Spawned Creep - " .. unit.name .. " - Count: ".. unit.count .. "\n");
end
end
end
return ROUND_DELAY
end)
Timers:CreateTimer(0.1, function()
local allHeroes = HeroList:GetAllHeroes()
for _,hero in pairs(allHeroes) do
local team = hero:GetTeam()
PlayerResource:ModifyGold(hero:GetPlayerOwnerID(), INCOME_COUNT*hero.income, false, 1)
end
return INCOME_DELAY
end)
end
function Precache( context )
-- Entire heroes (sound effects/voice/models/particles) can be precached with PrecacheUnitByNameSync
-- Custom units from npc_units_custom.txt can also have all of their abilities and precache{} blocks precached in this way
PrecacheUnitByNameSync("npc_dota_hero_dragon_knight", context)
PrecacheUnitByNameSync("npc_dota_hero_sniper", context)
PrecacheUnitByNameSync("npc_dota_hero_vengefulspirit", context)
PrecacheUnitByNameSync("npc_dota_hero_treant", context)
PrecacheUnitByNameSync("npc_dota_hero_omniknight", context)
PrecacheUnitByNameSync("npc_dota_hero_doom_bringer", context)
PrecacheUnitByNameSync("npc_dota_Hero_crystal_maiden", context)
end
-- Create the game mode when we activate
function Activate()
GameRules.GameMode = GameMode()
GameRules.GameMode:_InitGameMode()
end
$.Msg("JAVASCRIPT SUCCESFULLY LOADED!");
var unitConf = {};
var unitHaved = {};
const maxPages = 4;
var currentPage = 1;
var myincome = 1;
//Runs a function periodically
//start - how much of an additional delay to have (on top of the tick refresh) (set this to -1 to run the function immediately
//time - how long to run for. set this to -1 to run infinitely
//tick - how many seconds to elapse between ticks (assumes time / tick is an integer) (set this to negative to run a set amount of ticks, e.g. -30 will run 30 ticks in whatever time period given)
//func - func to run (return true to cancel)
//UPDATE June 29 2015 - fixed some enclosure issues, added a safecheck for time overflow
$.Every = function(start, time, tick, func){
var startTime = Game.Time();
var tickRate = tick;
if(tick < 1){
if(start < 0) tick--;
tickRate = time / -tick;
}
var tickCount = time/ tickRate;
if(time < 0){
tickCount = 9999999;
}
var numRan = 0;
$.Schedule(start, (function(start,numRan,tickRate,tickCount){
return function(){
if(start < 0){
start = 0;
if(func()){
return;
};
}
var tickNew = function(){
numRan++;
delay = (startTime+tickRate*numRan)-Game.Time();
/* if((startTime+tickRate*numRan)-Game.Time() < 0){
$.Msg('[ERROR] Function ' + func + ' taking too long to loop!')
delay = 0;
}*/
$.Schedule(delay, function(){
if(func()){
return;
};
tickCount--;
if(tickCount > 0) tickNew();
});
};
tickNew();
}
})(start,numRan,tickRate,tickCount));
};
$.Every(0, -1, -10, function(){
onJavaTimerTick();
});
function OnUnitBuySuccess(data)
{
myincome = data.income;
//$.Msg(data);
}
function onJavaTimerTick( )
{
if(Object.keys(unitConf).length == 0)
{
GameEvents.SendCustomGameEventToServer( "unitpanel_debug", {thisdata : 1} );
//$.Msg(unitConf);
}
$('#income-label').GetChild(1).text = myincome*10;
for(var i in unitConf)
{
if(currentPage == unitConf[i].page)
{
$(unitConf[i].unitclass).style.visibility = "visible";
}
else $(unitConf[i].unitclass).style.visibility = "collapse";
if(Players.GetGold(Players.GetLocalPlayer()) < unitConf[i].cost)
{
$(unitConf[i].unitclass).style.border = "5px solid #9b0000";
}
else
{
$(unitConf[i].unitclass).style.border = "5px solid #199900";
//Game.EmitSound("Quickbuy.Available");
}
}
}
function SelectPage(value)
{
if(currentPage + value > 0 && currentPage + value <= maxPages)
{
currentPage += value;
}
else if(currentPage + value == 0) currentPage = maxPages;
else currentPage = 1;
Game.EmitSound("ui.shortwhoosh");
$('#PageLabelNumber').text = currentPage;
}
function OnAllUnitsLoad( event_data )
{
unitConf = event_data;
for(var i in unitConf)
{
(function() {
var m = i;
var thisclass = $(unitConf[m].unitclass);
thisclass.GetChild(1).text = unitConf[m].cost;
var thislocal = $.Localize("#Game_tooltip_income")
+unitConf[m].income*10
+"<br>"+$.Localize("tooltip_"+m)+"<br>"
+"<br>"+$.Localize("Game_tooltip_health")+"<font color='#ffee00'>"+unitConf[m].health+"</font>"
+"<br>"+$.Localize("Game_tooltip_attackrange")+"<font color='#ffee00'>"+unitConf[m].attackrange+"</font>"
+"<br>"+$.Localize("Game_tooltip_damage")+"<font color='#ffee00'>"+unitConf[m].mindamage+"-"+unitConf[m].maxdamage+"</font>"
+"<br>"+$.Localize("Game_tooltip_armor")+"<font color='#ffee00'>"+unitConf[m].armor+"</font>";
if(unitConf[m].ancient == 1) thislocal = $.Localize("#Game_tooltip_ancient") + thislocal;
if(unitConf[m].ability1 != "")
{
thislocal = thislocal+"<br>"+$.Localize("Game_tooltip_ability") +"<font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability1)+"</font>";
if(unitConf[m].ability2 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability2)+"</font>";
if(unitConf[m].ability3 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability3)+"</font>";
if(unitConf[m].ability4 != "")
{
thislocal = thislocal+"<br><font color='#ff0000'>"+$.Localize("DOTA_Tooltip_ability_" + unitConf[m].ability4)+"</font>";
}
}
}
}
thisclass.SetPanelEvent("onmouseover", function(){ $.DispatchEvent("DOTAShowTextTooltip", thisclass, thislocal);});
thisclass.SetPanelEvent("onmouseout", function(){ $.DispatchEvent("DOTAHideTextTooltip", thisclass);});
})();
}
}
function OnPlayerUnitsLoad(data)
{
//$.Msg(data);
var newunits = {};
for(var i in data)
{
(function() {
var m = i;
var name = data[m].name
newunits[name] = {count: data[m].count, unitclass: "unitclass_"+name}
})();
}
ReloadCurrentUnitsPanel(newunits);
}
function ReloadCurrentUnitsPanel(units)
{
var unitlistlabel = $('#unitlist-label');
unitlistlabel.RemoveAndDeleteChildren();
delete unitHaved;
unitHaved = units;
for(i in unitHaved)
{
(function() {
var m = i;
if(unitHaved[m].count > 0)
{
var thispanel = $.CreatePanel("Button", unitlistlabel, unitHaved[m].unitclass );
var thislabel = $.CreatePanel("Label", thispanel, "label_"+unitHaved[m].unitclass);
thispanel.SetPanelEvent( 'onactivate', function(){ cmdSellUnit(m, 1);});
thispanel.AddClass("currentunit_list");
thislabel.AddClass("currentunit_list_label");
thispanel.style.border = "2px solid white";
thislabel.text = "$";
thislabel.style.visibility = "collapse";
thispanel.SetPanelEvent("onmouseover", function(){
thislabel.style.visibility = "visible";
thispanel.style.border = "3px solid yellow";
$.DispatchEvent("DOTAShowTextTooltip", thispanel, $.Localize("#Game_tooltip_sellunit")+$.Localize("#tooltip_"+m)+"<br>"+ $.Localize("#Game_tooltip_currentunitcount") + unitHaved[m].count);
});
thispanel.SetPanelEvent("onmouseout", function(){
thislabel.style.visibility = "collapse";
thispanel.style.border = "2px solid white";
$.DispatchEvent("DOTAHideTextTooltip", thispanel);
});
thispanel.style.backgroundSize = "100% 100%";
thispanel.style.backgroundImage = "url('file://{images}/custom_game/avatar_"+m+".png')";
}
})();
}
}
function cmdSellUnit(unitname, count)
{
if(unitHaved[unitname].count > 0)
{
$.Msg( "EVENT: unit_sell - true ");
var unitcount = 0;
for(var i in unitHaved)
{
(function(){
var m = i;
if(unitHaved[m].count > 0) unitcount += unitHaved[m].count;
//$.Msg(unitcount);
})();
}
if(unitcount > 4)
{
var data = {
name: unitname,
count: count
};
GameEvents.SendCustomGameEventToServer( "sell_unit", data );
$.Msg( "EVENT: unit_sell_success - true ");
Game.EmitSound("General.Sell");
}
else
{
Game.EmitSound("General.NoGold");
}
}
}
GameEvents.Subscribe( "unitbuy_success", OnUnitBuySuccess);
GameEvents.Subscribe( "load_allunits", OnAllUnitsLoad);
GameEvents.Subscribe( "load_playerunits", OnPlayerUnitsLoad);
function cmdBuyUnit(unitname, count)
{
$.Msg( "EVENT: unit_buy - true ");
if(Players.GetGold(Players.GetLocalPlayer()) >= unitConf[unitname].cost)
{
var data = {
name: unitname,
count: count
};
GameEvents.SendCustomGameEventToServer( "buy_unit", data );
$.Msg( "EVENT: unit_buy_success - true ");
Game.EmitSound("General.Buy");
}
else
{
Game.EmitSound("General.NoGold");
}
}
// UTILS