-- In this file we define functions that serves for Outposts windows ------------------------------------------------------------------------------------------------------------ -- create the game namespace without reseting if already created in an other file. if (game==nil) then game= {}; end -- init The Outpost Object if (game.Outpost==nil) then game.Outpost= {}; game.Outpost.LastTimeZoneUpdate= 0; end -- init constants, from XML defines if (game.OutpostEnums==nil) then game.OutpostEnums= {}; -- force values to be stored as int game.OutpostEnums.UnknownOutpostState= tonumber( getDefine('outpost_status_UnknownOutpostState') ); game.OutpostEnums.Peace= tonumber( getDefine('outpost_status_Peace') ); game.OutpostEnums.WarDeclaration= tonumber( getDefine('outpost_status_WarDeclaration') ); game.OutpostEnums.AttackBefore= tonumber( getDefine('outpost_status_AttackBefore') ); game.OutpostEnums.AttackRound= tonumber( getDefine('outpost_status_AttackRound') ); game.OutpostEnums.AttackAfter= tonumber( getDefine('outpost_status_AttackAfter') ); game.OutpostEnums.DefenseBefore= tonumber( getDefine('outpost_status_DefenseBefore') ); game.OutpostEnums.DefenseRound= tonumber( getDefine('outpost_status_DefenseRound') ); game.OutpostEnums.DefenseAfter= tonumber( getDefine('outpost_status_DefenseAfter') ); end -- *************************************************************************** -- *************************************************************************** -- OUTPOST COMMON -- *************************************************************************** -- *************************************************************************** ------------------------------------------------------------------------------------------------------------ function game:outpostSetTimeZone(tz) setDbProp('UI:SAVE:OUTPOST:TIME_ZONE', tz); end ------------------------------------------------------------------------------------------------------------ function game:outpostDisplayTimeZone(uiLocal) local tz= getDbProp('UI:SAVE:OUTPOST:TIME_ZONE'); local uiGroup= getUICaller(); uiGroup[uiLocal].uc_hardtext= 'GMT ' .. string.format('%+d', tz); end ------------------------------------------------------------------------------------------------------------ function game:outpostAdjustHour(uiLocal, prop) local uiGroup = getUICaller(); local tz = getDbProp('UI:SAVE:OUTPOST:TIME_ZONE'); local h = runExpr(prop); -- add time zone and clamp hour h = math.fmod(h + tz + 24, 24); uiGroup[uiLocal].uc_hardtext = string.format('%02d:00', h); end ------------------------------------------------------------------------------------------------------------ function game:outpostUpdateTimeZone() -- update time zone auto? local tzAuto= getDbProp('UI:SAVE:OUTPOST:TIME_ZONE_AUTO'); if(tzAuto==0) then return; end -- every 5 seconds? local curTick= getDbProp('UI:VARIABLES:CURRENT_SERVER_TICK'); if(curTick - game.Outpost.LastTimeZoneUpdate > 50) then game.Outpost.LastTimeZoneUpdate= curTick; runAH(nil,'outpost_update_time_zone_auto',''); end end ------------------------------------------------------------------------------------------------------------ function game:outpostIsStatusWar(status) -- return true only if the status is a War if( status == self.OutpostEnums.UnknownOutpostState or status == self.OutpostEnums.Peace or status == self.OutpostEnums.WarDeclaration )then return false; else return true; end end ------------------------------------------------------------------------------------------------------------ function game:outpostIsStatusWarRound(status) -- return true only if the status is an attack period if( status == self.OutpostEnums.AttackRound or status == self.OutpostEnums.DefenseRound ) then return true; else return false; end end ------------------------------------------------------------------------------------------------------------ function game:outpostBCOpenStateWindow() -- Open the State Window from the BotChat. server msg runAH(nil, 'outpost_select_from_bc', ''); -- Open the window runAH(nil, 'show', 'outpost_selected'); end ------------------------------------------------------------------------------------------------------------ function game:outpostDeclareWar() -- Send Msg to server runAH(nil, 'outpost_declare_war_start', ''); -- wait a ack from server. Suppose not OK by default setDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_RECEIVED", 0); setDbProp("UI:TEMP:OUTPOST:DECLARE_WAR_ACK_OK", 0); -- Open the Declare War window runAH(nil, "show", "outpost_declare_war"); end ------------------------------------------------------------------------------------------------------------ function game:outpostDeclareWarValidate() -- Send Msg to server runAH(nil, 'outpost_declare_war_validate', ''); -- close the Declare War window runAH(nil, "hide", "outpost_declare_war"); end ------------------------------------------------------------------------------------------------------------ -- some constants game.Outpost.SelectSquadCapitalModal= 'ui:interface:squad_change_capital'; game.Outpost.SelectSquadCapitalEditBox= 'ui:interface:squad_change_capital:edit:eb'; ------------------------------------------------------------------------------------------------------------ function game:outpostSelectSquadCapitalOpen() -- Retrieve the the edit box. local uiEB= getUI(self.Outpost.SelectSquadCapitalEditBox); if(uiEB==nil) then return; end -- Retrieve the value in database local dbPath= formatUI('SERVER:GUILD:OUTPOST:O#1', math.max(0, getDbProp('UI:TEMP:OUTPOST:SELECTION')) ); local val= getDbProp(dbPath .. ':SQUAD_CAPITAL'); -- Open the modal runAH(getUICaller(), "enter_modal", "group=" .. game.Outpost.SelectSquadCapitalModal); -- Setup the default input string with it, and set focus uiEB.input_string= val; runAH(nil, "set_keyboard_focus", "target=" .. self.Outpost.SelectSquadCapitalEditBox .. "|select_all=true"); end ------------------------------------------------------------------------------------------------------------ function game:outpostSelectSquadCapitalConfirm() -- Retrieve the value in the edit box. local uiEB= getUI(self.Outpost.SelectSquadCapitalEditBox); if(uiEB==nil) then return; end local val= uiEB.input_string; if( tonumber(val) == nil ) then return; end -- Send a msg to server runAH(nil, "outpost_select_squad_capital", val); -- Close the modal runAH(nil, "leave_modal", ""); end ------------------------------------------------------------------------------------------------------------ function game:outpostToolTipTrainSquad(dbIndex) local halfMaxSquad= tonumber(getDefine("outpost_nb_max_squad_in_list")); -- compute the level at which the squad will spawn. local lvl; if(dbIndex < halfMaxSquad) then lvl= dbIndex*2 +1 ; -- eg: 0 => 1. 1=> 3 else lvl= (dbIndex-halfMaxSquad)*2 +2 ; -- eg: 12 => 2 end -- set the tooltip local text = i18n.get('uittOutpostSquadLvl'); text = findReplaceAll(text, "%lvl", tostring(lvl)); setContextHelpText(text); end -- *************************************************************************** -- *************************************************************************** -- OUTPOST INFO WINDOW -- *************************************************************************** -- *************************************************************************** ------------------------------------------------------------------------------------------------------------ function game:outpostInfoGetDbPath(uiGroup) if (uiGroup.Env.Type==0) then return 'SERVER:OUTPOST_SELECTED'; else -- avoid problems, points to 0 if nothing selected return formatUI('SERVER:GUILD:OUTPOST:O#1', math.max(0, getDbProp('UI:TEMP:OUTPOST:SELECTION')) ); end end ------------------------------------------------------------------------------------------------------------ function game:outpostInfoOnDraw() local uiGroup= getUICaller(); -- get status local path= self:outpostInfoGetDbPath(uiGroup); local status= getDbProp(path .. ':STATUS'); -- translate ticks to time local curTick= getDbProp('UI:VARIABLES:CURRENT_SERVER_TICK'); local endTick= getDbProp( path .. ':STATE_END_DATE' ); -- suppose a server tick is 100 ms local timeSec= (endTick - curTick)/10; timeSec= math.max(timeSec, 0); -- readable form if (status == self.OutpostEnums.Peace) then uiGroup.Env.Timer.uc_hardtext= ''; else uiGroup.Env.Timer.uc_hardtext= '(' .. runFct('secondsToTimeString', timeSec) .. ')'; end end ------------------------------------------------------------------------------------------------------------ function game:outpostInfoOnDbChange() local uiGroup= getUICaller(); -- get the selection local path= self:outpostInfoGetDbPath(uiGroup); -- change path for icon and textid uiGroup.global_state.outpost_owner.guild.blason.sheet= path .. ':GUILD'; uiGroup.global_state.outpost_owner.guild.name.textid_dblink= path .. ':GUILD:NAME'; -- change path for attacker text id uiGroup.global_state.outpost_attacker.name.textid_dblink= path .. ':GUILD:NAME_ATT'; end ------------------------------------------------------------------------------------------------------------ function game:outpostInitInfo(type) local uiGroup= getUICaller(); -- bkup Timer control uiGroup.Env.Timer= uiGroup.global_state.outpost_status_time; uiGroup.Env.Type= type; -- must change timer each frame setOnDraw(uiGroup, 'game:outpostInfoOnDraw()'); -- For Type==1 (outpost from GuildInfo), must change the DB Path for the GuildIcon, and GuildName TextId if(type==1) then addOnDbChange(uiGroup,"@UI:TEMP:OUTPOST:SELECTION", 'game:outpostInfoOnDbChange()'); end end ------------------------------------------------------------------------------------------------------------ function game:outpostActiveDefenderHourButton() -- uiGroup here should be the 'war_schedule' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local owned= getDbProp(path .. ':OWNED'); local admin= getDbProp('SERVER:USER:OUTPOST_ADMIN'); local status= getDbProp(path .. ':STATUS'); -- status start with 3 for Actual War (2 for War Declaration). If the user has not the right to change the defense period -- if the player has no right to edit if( owned==0 or admin==0 or self:outpostIsStatusWar(status) ) then uiGroup.outpost_def_hour.frozen= true; uiGroup.outpost_def_hour.tooltip= i18n.get('uittOutpostDefHourCannotEdit'); else uiGroup.outpost_def_hour.frozen= false; -- get defense hours in 0-23 range local timeRangeDef= getDbProp(path .. ':TIME_RANGE_DEF'); local timeRangeDefWanted= getDbProp(path .. ':TIME_RANGE_DEF_WANTED'); timeRangeDef= secondsSince1970ToHour( timeRangeDef ); timeRangeDef= math.fmod(timeRangeDef+24, 24); timeRangeDefWanted= math.fmod(timeRangeDefWanted+24, 24); -- if time required is the one obtained, or if we are in peace if( timeRangeDef == timeRangeDefWanted or status<=game.OutpostEnums.Peace ) then uiGroup.outpost_def_hour.tooltip= i18n.get('uittOutpostDefHour'); else uiGroup.outpost_def_hour.tooltip= i18n.get('uittOutpostDefHourError'); end end -- Force the tooltip to be up to date (important if dbs are desync) disableContextHelpForControl(uiGroup.outpost_def_hour); end ------------------------------------------------------------------------------------------------------------ function game:outpostActiveAttackerHourButton() -- uiGroup here should be the 'war_schedule' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local canEdit= getDbProp('UI:TEMP:OUTPOST:DECLARE_WAR_ACK_OK'); -- status start with 3 for Actual War (2 for War Declaration). If the user has not the right to change the defense period -- if the player has no right to edit if( canEdit==0 ) then uiGroup.outpost_att_hour.frozen= true; uiGroup.outpost_att_hour.tooltip= i18n.get('uittOutpostAttHour'); else uiGroup.outpost_att_hour.frozen= false; -- get attack hours in 0-23 range local timeRangeAtt= getDbProp('UI:TEMP:OUTPOST:DECLARE_WAR_ACK_TIME_RANGE_ATT'); local timeRangeAttWanted= getDbProp('UI:TEMP:OUTPOST:DECLARE_WAR_ATTACK_PERIOD'); timeRangeAtt= secondsSince1970ToHour( timeRangeAtt ); timeRangeAtt= math.fmod(timeRangeAtt+24, 24); timeRangeAttWanted= math.fmod(timeRangeAttWanted+24, 24); -- if time required is the one obtained if( timeRangeAtt == timeRangeAttWanted ) then uiGroup.outpost_att_hour.tooltip= i18n.get('uittOutpostAttHour'); else uiGroup.outpost_att_hour.tooltip= i18n.get('uittOutpostAttHourError'); end end -- Force the tooltip to be up to date. important here because -- DECLARE_WAR_ACK_TIME_RANGE_ATT(server) is received after DECLARE_WAR_ATTACK_PERIOD(local) disableContextHelpForControl(uiGroup.outpost_att_hour); end ------------------------------------------------------------------------------------------------------------ function game:outpostIsGuildInvolved() local found = 0; local sheetCur; -- try to get sheet id from bot object local sheetSel = getDbProp('SERVER:OUTPOST_SELECTED:SHEET'); if (sheetSel == 0) then -- try to get sheet id from outpost manager local ind = getDbProp('UI:TEMP:OUTPOST:SELECTION'); if (ind == -1) then return 0; end sheetSel = getDbProp(formatUI('SERVER:GUILD:OUTPOST:O#1', ind) .. ':SHEET'); end -- check every outpost owned or challenged by the guild local i; for i = 0, 15 do sheetCur = getDbProp(formatUI('SERVER:GUILD:OUTPOST:O#1', i) .. ':SHEET'); if (sheetCur == sheetSel) then found = 1; end end return found; end ------------------------------------------------------------------------------------------------------------ function game:outpostGetStatusInfo(statusExpr, dbIndex, isTooltip) local uiGroup = getUICaller(); local status = runExpr(statusExpr); local uittOutpost; local path; -- get outpost if (isTooltip == 'no') then path = self:outpostInfoGetDbPath(uiGroup.parent); else path = formatUI('SERVER:GUILD:OUTPOST:O#1', math.max(0, dbIndex)); end -- Peace if (status == self.OutpostEnums.Peace) then uittOutpost = i18n.get('uittOutpostPeace'); -- WarDeclaration elseif (status == self.OutpostEnums.WarDeclaration) then if (isTooltip == 'yes' or self:outpostIsGuildInvolved() == 1) then local myGuild = getDbProp('SERVER:GUILD:NAME'); local outpostGuild = getDbProp('SERVER:OUTPOST_SELECTED:GUILD:NAME'); local outpostTribe = getDbProp('SERVER:OUTPOST_SELECTED:GUILD:TRIBE'); -- bot object flag : check 'owned' param to determine who are the attacker and defender if (outpostTribe == 0 and outpostGuild == 0) then local owned = getDbProp(path .. ':OWNED'); if (owned == 1) then uittOutpost = i18n.get('uittOutpostWarDeclarationMyGuildDefend'); else uittOutpost = i18n.get('uittOutpostWarDeclarationMyGuildAttack'); end -- outpost manager : check guild name to determine who are the attacker and defender else if (myGuild == outpostGuild) then uittOutpost = i18n.get('uittOutpostWarDeclarationMyGuildDefend'); else uittOutpost = i18n.get('uittOutpostWarDeclarationMyGuildAttack'); end end else uittOutpost = i18n.get('uittOutpostWarDeclaration'); end -- AttackBefore elseif (status == self.OutpostEnums.AttackBefore) then uittOutpost = i18n.get('uittOutpostAttackBefore'); -- AttackRound elseif (status == self.OutpostEnums.AttackRound) then uittOutpost = i18n.get('uittOutpostAttackRound'); -- AttackAfter elseif (status == self.OutpostEnums.AttackAfter) then local lvlMax = getDbProp(path .. ':ROUND_LVL_THRESHOLD'); local lvlAtt = getDbProp(path .. ':ROUND_LVL_MAX_ATT'); if (lvlAtt > lvlMax) then uittOutpost = i18n.get('uittOutpostAttackAfterWin'); else uittOutpost = i18n.get('uittOutpostAttackAfterLoose'); end -- DefenseBefore elseif (status == self.OutpostEnums.DefenseBefore) then uittOutpost = i18n.get('uittOutpostDefenseBefore'); -- DefenseRound elseif (status == self.OutpostEnums.DefenseRound) then uittOutpost = i18n.get('uittOutpostDefenseRound'); -- DefenseAfter elseif (status == self.OutpostEnums.DefenseAfter) then uittOutpost = i18n.get('uittOutpostDefenseAfter'); -- default else uittOutpost = i18n.get('uittOutpostPeace'); end return uittOutpost; end ------------------------------------------------------------------------------------------------------------ function game:outpostDisplayStatusInfo(statusExpr, id) local uiGroup = getUICaller(); local text = self:outpostGetStatusInfo(statusExpr, -1, 'no'); uiGroup[id].uc_hardtext_format = text; end ------------------------------------------------------------------------------------------------------------ function game:outpostDisplayStatusInfoTooltip(statusExpr, dbIndex) local text = self:outpostGetStatusInfo(statusExpr, dbIndex, 'yes'); setContextHelpText(text); end ------------------------------------------------------------------------------------------------------------ function game:outpostUpdateBuildingSheet(buildingIndex) local ui= getUICaller(); local outpostIndex= getDbProp('UI:TEMP:OUTPOST:SELECTION'); if (outpostIndex<0) then outpostIndex= 0; end local db= 'SERVER:GUILD:OUTPOST:O' .. tostring(outpostIndex) .. ':BUILDINGS:' .. tostring(buildingIndex) ; ui.building_sheet.sheet= db; end -- *************************************************************************** -- *************************************************************************** -- OUTPOST INFO: ROUND STATE DISPLAY -- *************************************************************************** -- *************************************************************************** ------------------------------------------------------------------------------------------------------------ -- ROUND_LVL_THRESHOLD function game:outpostChangeRoundLvlThreshold() -- uiGroup here should be the 'round_state' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local val= getDbProp(path .. ':ROUND_LVL_THRESHOLD'); -- setup text uiGroup.outpost_lvl_thre.uc_hardtext= tostring(val); end ------------------------------------------------------------------------------------------------------------ -- ROUND_LVL_MAX_ATT function game:outpostChangeRoundLvlMaxAtt() -- uiGroup here should be the 'round_state' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local val= getDbProp(path .. ':ROUND_LVL_MAX_ATT'); local status= getDbProp(path .. ':STATUS'); -- setup text (only relevant when attack period has begun) if(status>=self.OutpostEnums.AttackRound) then uiGroup.outpost_lvl_max_att.uc_hardtext= tostring(val); else uiGroup.outpost_lvl_max_att.uc_hardtext= '- '; end end ------------------------------------------------------------------------------------------------------------ -- ROUND_LVL_MAX_DEF function game:outpostChangeRoundLvlMaxDef() -- uiGroup here should be the 'round_state' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local val= getDbProp(path .. ':ROUND_LVL_MAX_DEF'); local status= getDbProp(path .. ':STATUS'); -- setup text (only relevant in War) if(status>=self.OutpostEnums.DefenseRound) then uiGroup.outpost_lvl_max_def.uc_hardtext= tostring(val); else uiGroup.outpost_lvl_max_def.uc_hardtext= '- '; end end ------------------------------------------------------------------------------------------------------------ -- ROUND_LVL_CUR function game:outpostChangeRoundLvlCur() -- uiGroup here should be the 'round_state' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local val= getDbProp(path .. ':ROUND_LVL_CUR'); local status= getDbProp(path .. ':STATUS'); -- add 1, because server send a 0 based value val= val+1; -- setup text (only in a Attack/Defense Round) if(self:outpostIsStatusWarRound(status)) then uiGroup.outpost_lvl_cur.uc_hardtext= tostring(val); else uiGroup.outpost_lvl_cur.uc_hardtext= '- '; end end ------------------------------------------------------------------------------------------------------------ -- ROUND_ID_CUR / ROUND_ID_MAX function game:outpostChangeRoundId() -- uiGroup here should be the 'round_state' uigroup (not the whole parent infoGroup) local uiGroup= getUICaller(); -- get values local path= self:outpostInfoGetDbPath(uiGroup.parent); local val= getDbProp(path .. ':ROUND_ID_CUR'); local maxRound= getDbProp(path .. ':ROUND_ID_MAX'); local status= getDbProp(path .. ':STATUS'); -- add 1 because server sends a 0 based value val= val+1; -- setup text (only in a Attack/Defense Round) if(self:outpostIsStatusWarRound(status)) then uiGroup.outpost_round_cur.uc_hardtext= tostring(val) .. ' / ' .. tostring(maxRound); else uiGroup.outpost_round_cur.uc_hardtext= '- '; end end -- *************************************************************************** -- *************************************************************************** -- OUTPOST PVP INFO / PROPOSAL -- *************************************************************************** -- *************************************************************************** ------------------------------------------------------------------------------------------------------------ function game:outpostPvpJoin(choice) -- send msg server runAH(nil, 'outpost_pvp_join', choice); -- hide the window runAH(nil, 'hide', 'join_pvp_outpost_proposal'); end ------------------------------------------------------------------------------------------------------------ function game:outpostPvpJoinTimerOnDraw() local uiGroup= getUICaller(); -- Compute time left local curTick= getDbProp('UI:VARIABLES:CURRENT_SERVER_TICK'); local endTick= getDbProp('UI:TEMP:OUTPOST:PVP_PROPOSAL_TICK_END'); local timeSec= (endTick - curTick)/10; timeSec= math.max(timeSec, 0); timeSec= math.floor(timeSec+0.5); -- replace in str local text= i18n.get('uiOutpostJoinPVPTimer'); text= findReplaceAll(text, "%time", tostring(timeSec)); uiGroup.Env.Timer.uc_hardtext_format= text; end ------------------------------------------------------------------------------------------------------------ function game:outpostInitPvpJoinTimer() local uiGroup= getUICaller(); -- bkup Timer viewtext uiGroup.Env.Timer= uiGroup.text; -- must change timer each frame setOnDraw(uiGroup, 'game:outpostPvpJoinTimerOnDraw()'); end