Excellent.
Some of the issues I have seen so far in Veydurs mod. When it adds a New Resource, the resource doesn't seem to show up as useable. So if I get an extra Iron I still can't build a new Swordsman.
Also when it adds bonus yields to tiles they don't usually show up in the city view. Sometimes I think it may actually cancel out the normal effects of the tile.
For example I had 1added to a Mine I was working. Once I went into city view none of the
's would show at all. I couldn't figure out if it was just a display issue or an actual missing resource issue. Didn't seem as if the
for the city added up correctly no matter what I did.
Also if say Wheat is added to a farmed hex, the wheat shows up above the farm unless the game is saved and then reopened. Again just a display thing.
The Color Text is written on the window of the event when it pops up. But the actual Effects of the Event are only shown when hovering over the Button. It is possible to add the effect to the actual text into the main window?
UserEventAdd{
id = "MYTHEVENT_LOW_LM",
probability = 0.02,
alignment = "LM",
condition = Low_Cond,
this_event_limit = 20;
any_event_limit = 5;
options = {
OPTION_L = { order = 1, condition = Once_Cond, effect = Effect_Low_LM_L, flavor1 = "FLAVOR_PRODUCTION", flavor2 = "FLAVOR_SCIENCE" },
OPTION_C = { order = 2, condition = Once_Cond, effect = Effect_Low_LM_C, flavor1 = "FLAVOR_GROWTH", flavor2 = "FLAVOR_GOLD" },
OPTION_M = { order = 3, condition = Once_Cond, effect = Effect_Low_LM_M, flavor1 = "FLAVOR_GROWTH", flavor2 = "FLAVOR_PRODUCTION" },
OPTION_E = { order = 4, condition = Once_Cond, effect = Effect_Low_LM_E, flavor1 = "FLAVOR_GOLD", flavor2 = "FLAVOR_SCIENCE" },
}
};
function AnyUserEventLastAppeared( player_id )
-- I made this!
local game_turn = -99;
if( player_id ~= nil ) then
local log_event_id="";
local event_log;
for log_event_id, _ in pairs( UserEventsLogTable ) do
if (log_event_id ~= 0) then
local testval = UserEventLastAppeared( log_event_id, player_id );
if ( testval > game_turn) then game_turn = testval end;
end
end
end
return game_turn;
end
function UserEventsHandlerProcess( event_table, scheduled )
local func_ret = false;
local aID = Game.GetActivePlayer();
for index,pPlayer in pairs(Players) do
if (pPlayer:IsAlive() and not (pPlayer:IsMinorCiv() or pPlayer:IsBarbarian() ) ) then
-- Don't want dead civs, minor civs, or barbarians to get events.
local playerID = pPlayer:GetID();
-- cycle through events
for event_i, event in pairs( event_table ) do
-- perform an event condition check, only if the event would occur
-- The old logic would block the event if you gave this condition to all outcomes, but this is faster
local event_valid = true;
if type( event.condition ) == "function" then
event_valid = event.condition( pPlayer );
end
if ( event.this_event_limit ~= nil ) then
-- Sometimes, we want an event to lock itself out for a time.
local thisLimit = event.this_event_limit;
local CheckThis = UserEventLastAppeared( event.id, playerID );
if ( thisLimit > 0 ) then
-- a positive value means ban if this particular event has happened recently
if ( (Game:GetGameTurn() - CheckThis) < thisLimit ) then
event_valid = false;
end
elseif ( thisLimit < 0 ) then
-- a value of -1 means ban if this event has EVER occurred
if ( CheckThis >= 0 ) then
event_valid = false;
end
end
end
if ( event.any_event_limit ~= nil ) then
-- Sometimes, we want events to ALL lock each other out for a brief period.
local TimeCheckAny = Game:GetGameTurn() - AnyUserEventLastAppeared( playerID ); -- No two events should be within a few turns of each other, ever.
if ( TimeCheckAny < event.any_event_limit ) then
event_valid = false;
end
end
if ( event_valid ) then
local rand_res = math.random( 20000 ) / ( 20000.0 );
local test_prob = event.probability;
test_prob = test_prob * AlignMult(playerID, event.alignment); -- ranges from 0.5 to 1.5, more or less.
if scheduled or rand_res < test_prob then
local is_valid_event = false;
local valid_elems = {};
for option_i, option in pairs( event.options ) do
local is_valid_option = true;
if type( option.condition ) == "function" then
is_valid_option = false;
-- check the cities and surrounding plots
for city in pPlayer:Cities() do
local cityID = city:GetID();
for i = 0, city:GetNumCityPlots() - 1, 1 do
local plot = city:GetCityIndexPlot( i );
if plot ~= nil and plot:GetOwner() == playerID then
local params = { playerID, cityID, nil, { x = plot:GetX(), y = plot:GetY() } };
local cond_res = option.condition( pPlayer, city, nil, plot );
if cond_res then
is_valid_option = true;
table.insert( valid_elems, params );
end
end
end -- for i
end -- for city
-- check the units
for unit in pPlayer:Units() do
local unitID = unit:GetID();
local unit_plot = unit:GetPlot();
local unit_params = { playerID, nil, unitID, { x = unit_plot:GetX(), y = unit_plot:GetY() } };
local cond_res = option.condition( pPlayer, nil, unit, unit_plot );
if cond_res then
is_valid_option = true;
table.insert( valid_elems, unit_params );
end
end -- for unit
end -- if type ( option.condition ) == "function"
UserEventsTable[ event.id ].options[ option_i ].is_valid = is_valid_option;
if is_valid_option then
is_valid_event = true;
end
end -- for option_i, option
if is_valid_event then
_Shuffle( valid_elems );
UserEventsTable[ event.id ]._elem = valid_elems[ 1 ];
UserEventLog( event.id, playerID );
LuaEvents.UserEventsPopupBuild( event );
func_ret = true;
if not scheduled then
break;
end
end
end -- if scheduled or rand_res < event.probability
end -- If we met the event condition (if any)
end -- for event_i, event
end -- Valid player?
end -- loop over players
return func_ret;
end
Events.ActivePlayerTurnStart.Add(UserEventsHandler);
function BuildUserEventPopup( event )
if ( event ~= nil ) then
local playerID, cityID, unitID, plot_coords = unpack( event._elem );
if playerID == nil or plot_coords == nil then
return;
end
local aID = Game.GetActivePlayer(); -- TODO: handle AI players, using flavor option value to determine the preferred choice
local pPlayer = Players[ playerID ];
local pCity = pPlayer:GetCityByID( cityID );
local pUnit = pPlayer:GetUnitByID( unitID );
local pPlot = Map.GetPlot( plot_coords.x, plot_coords.y );
local hex = ToHexFromGrid( Vector2( plot_coords.x, plot_coords.y ) );
local i18n_data = { pPlayer:GetName(), ( pCity and pCity:GetName() ) or "", ( pUnit and Locale.ConvertTextKey( GameInfo.Units[ pUnit:GetUnitType() ].Description ) ) or "" };
local event_title_i18n = "TXT_KEY_USER_EVENT_" .. event.id;
local event_desc_i18n = "TXT_KEY_USER_EVENT_" .. event.id .. "_DESC";
if ( playerID == aID ) then
Events.GameplayFX( hex.x, hex.y, -1 );
Events.SerialEventHexHighlight( hex, false, Vector4( 0.0, 1.0, 0.0, 1 ) );
UI.LookAt( pPlot, 0 );
local controlTable = {};
Controls.EventTitle:SetText( Locale.ConvertTextKey( event_title_i18n, unpack( i18n_data ) ) );
Controls.EventDescription:SetText( Locale.ConvertTextKey(event_desc_i18n, unpack( i18n_data ) ) );
CivIconHookup( playerID, 64, Controls.CivIcon, Controls.CivIconBG, Controls.CivIconShadow, false, true );
Controls.EventInfoStack:CalculateSize();
Controls.EventInfoStack:ReprocessAnchoring();
Controls.EventOptionStack:DestroyAllChildren();
end
local event_options = {};
local ParamWrapper = function( callback )
callback( pPlayer, pCity, pUnit, pPlot );
end
local offs_y = 0;
local options = {};
for optID, option in pairs( event.options ) do
option.__id = optID;
table.insert( options, option );
end
table.sort( options, function( a, b ) return a.order < b.order; end );
if ( playerID == aID ) then
for o_i, option in pairs( options ) do
local optID = option.__id;
local opt = {};
local option_i18n = event_title_i18n .."_" .. optID;
local option_desc_i18n = option.description or option_i18n .. "_DESC";
local option_tip_i18n = option.tooltip or option_i18n .. "_TIP";
ContextPtr:BuildInstanceForControl( "EventOptionInstance", opt, Controls.EventOptionStack );
opt.EventOptionDescription:SetOffsetVal( 35, offs_y );
opt.EventOptionDescription:SetText( Locale.ConvertTextKey( option_desc_i18n, unpack( i18n_data ) ) );
if not option.is_valid then
opt.EventOptionDescription:SetColor( Vector4( 0.3, 0.3, 0.3, 1 ), 0 );
opt.EventOptionButton:SetHide( true );
else
local but_txt;
if #options == 1 then
but_txt = "TXT_KEY_USER_EVENT_OPTION_OK";
else
but_txt = "TXT_KEY_USER_EVENT_OPTION_SELECT";
end
opt.EventOptionButton:SetText( Locale.ConvertTextKey( but_txt ) );
opt.EventOptionButton:RegisterCallback( Mouse.eLClick, function() option.effect( pPlayer, pCity, pUnit, pPlot ); Controls.FullScreenOverlay:SetHide( true ); end )
end
local tool_tip = Locale.ConvertTextKey( option_tip_i18n, unpack( i18n_data ) );
opt.EventOptionDescription:SetToolTipString( tool_tip );
opt.EventOptionButton:SetToolTipString( tool_tip );
opt.EventOptionButton:SetOffsetVal( 0, offs_y );
offs_y = offs_y + opt.EventOptionDescription:GetSizeY() + 50;
end
Controls.EventOptionStack:CalculateSize();
Controls.EventOptionStack:SetSizeY( offs_y );
Controls.EventOptionStack:SetOffsetVal( 0, Controls.EventInfoStack:GetSizeY() + 50 );
Controls.EventOptionStack:ReprocessAnchoring();
Controls.MainGrid:SetSizeY( Controls.EventInfoStack:GetSizeY() + offs_y + 20 );
Controls.BlackGridFrame:SetSizeY( Controls.MainGrid:GetSizeY() );
Controls.FullScreenOverlay:SetHide( false );
else
-- It's an AI, don't set up any windows, but just do the selection directly.
local nValid = 0;
local optID = {};
local optWeight = {};
local totWeight = 0.0;
local Fnum = DirCheck(playerID); -- 4-element array showing how many gods are available in each direction.
local Ltype = GameInfo.Leaders[pPlayer:GetLeaderType()].Type;
for o_i, option in pairs( options ) do
if ( option.is_valid ) then
nValid = nValid + 1;
optID[nValid] = option.__id;
optWeight[nValid] = Fnum[option.order]*1.0; -- Fnum+1? So that it CAN pick a direction with zero?
local flav1 = option.flavor1;
if ( flav1 ~= nil ) then
local condition1 = "LeaderType = '" .. Ltype .. "' and FlavorType = '"..flav1.."'";
for row in GameInfo.Leader_Flavors(condition1) do
optWeight[nValid] = optWeight[nValid] * (0.5 + row.Flavor/10.0);
end
end
local flav2 = option.flavor2;
if ( flav2 ~= nil ) then
local condition2 = "LeaderType = '" .. Ltype .. "' and FlavorType = '"..flav2.."'";
for row in GameInfo.Leader_Flavors(condition2) do
optWeight[nValid] = optWeight[nValid] * (0.5 + row.Flavor/10.0);
end
end
local flav3 = option.flavor3;
if ( flav3 ~= nil ) then
local condition3 = "LeaderType = '" .. Ltype .. "' and FlavorType = '"..flav3.."'";
for row in GameInfo.Leader_Flavors(condition3) do
optWeight[nValid] = optWeight[nValid] * (0.5 + row.Flavor/10.0);
end
end
totWeight = totWeight + optWeight[nValid];
end
end
if ( totWeight < 0.01 ) then
-- No direction had any choices.
optWeight = {1.0,1.0,1.0,1.0};
totWeight = nValid*1.0;
end
local diceroll = Map.Rand(totWeight*100,"AI event selection") / 100.0;
for ii = 1,nValid do
if ( diceroll >= 0.0 and diceroll < optWeight[ii]) then
for o_i, option in pairs( options ) do
if ( option.is_valid and option.__id == optID[ii] ) then
-- This is the right one. Trigger the effect.
option.effect( pPlayer, pCity, pUnit, pPlot );
diceroll = -999.0; -- prevents multiple options from triggering.
end
end
else
diceroll = diceroll - optWeight[ii];
end
end
end
end
end
LuaEvents.UserEventsPopupBuild.Add(BuildUserEventPopup);
First of all you only make changes to the UserEventAdd part?
Second I'm not sure how the effects and conditions in the old events mod correspond to the conditions and events you state. The old mod already has conditions so can these just be used instead if Low_Cond / Once_Cond?
Third you just use three flavor categories in your example. Can you use more: FLAVOR_CULTURE, FLAVOR_GREAT_PEOPLE, FLAVOR_HAPPINESS, ...?
I posted one event that I updated according to your instructions. Would you have a look at it?
function Low_Cond( player )
return Myth_Cond(player) and Game:GetGameTurn() > 5;
end
function Once_Cond ( player, city, unit, plot )
return city and city:IsCapital() and plot:IsCity();
end
@skodkim: You may be well off starting a new thread once you get it to work.
--[[ Wandering Wiseman ]]--
function WanderingWisemanCond( player, city, unit, plot )
return city and city:IsCapital() and plot:IsCity();
end
function WanderingWisemanCond1( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
return WanderingWisemanCond( player, city, unit, plot ) and player:GetGold() >= (200 + ncounter*50) ;
end
function WanderingWisemanCond2( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
return WanderingWisemanCond( player, city, unit, plot ) and player:GetGold() >= (100 + ncounter*25) ;
end
function WanderingWisemanNoEffect( player, city, unit, plot )
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT_N ONE" ) );
end
function WanderingWisemanEffect1( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
player:ChangeGold( - (200 + ncounter*50) );
_AddNewUnit( player, "UNIT_SCIENTIST", plot:GetX(), plot:GetY() );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT1" ) );
end
function WanderingWisemanEffect2( player, city, unit, plot )
local mera = player:GetCurrentEra();
local mcounter = 0;
if mera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
mcounter = 1;
elseif mera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
mcounter = 2;
elseif mera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
mcounter = 3;
elseif mera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
mcounter = 4;
elseif mera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
mcounter = 5;
elseif mera == GameInfo.Eras[ "ERA_MODERN" ].ID then
mcounter = 6;
else
mcounter = 7;
end
player:ChangeGold ( - (100 + mcounter*25) );
local res = math.random( 0, 99 );
if res < 35 then
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 40;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 70;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 122;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 214;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 375;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 656;
else
ncounter = 1148;
end
player:GetCurrentCultureBonus(ncounter);
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2A " ) );
elseif res < 40 then
player:SetNumFreeTechs( 1 );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2B " ) );
Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH,
Data1 = player,
Data3 = -1
} );
elseif res < 60 then
local tech = player:GetCurrentResearch();
_PlayerSetTech( player, tech, true );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2C " ) );
Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH,
Data1 = player,
Data3 = tech
} );
elseif res < 95 then
local turns = math.random( 2, 4 );
player:ChangeGoldenAgeTurns( turns );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2D ", turns ) );
else
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2E " ) );
end
end
UserEventAdd{
id = "WANDERING_WISEMAN",
probability = 0.002,
condition = Low_Cond,
this_event_limit = 20;
any_event_limit = 5;
options = {
OPTION_L = { order = 1, condition = WanderingWisemanCond1, effect = WanderingWisemanEffect1, flavor1 = "FLAVOR_GROWTH", flavor2 = "FLAVOR_SCIENCE" },
OPTION_C = { order = 2, condition = WanderingWisemanCond2, effect = WanderingWisemanEffect2, flavor1 = "FLAVOR_SCIENCE", flavor2 = "FLAVOR_SCIENCE" },
OPTION_M = { order = 3, condition = WanderingWisemanCond, effect = WanderingWisemanNoEffect, flavor1 = "FLAVOR_GOLD", flavor2 = "FLAVOR_GROWTH" },
}
};
--[[ / Wandering Wiseman ]]--
I'm sorry for being such a mod-noob but I'm not sure I get how Low_Cond / Once_Cond works entirely...
Generally I think Its a good idea to make some kind of checks saying that an event shouldn't occur within the first xxx rounds, within xxx rounds from the last event and such. That's all they do, right?
But if that's all they do how do I make sure that an event only occurs e.g. on a tile with farms, in the capital, ...?
function CapitalFarmCond(player, city, unit, plot)
local retval = false;
if ( player ~= nil and city ~= nil and plot ~= nil ) then
if ( city:IsCapital() and plot:GetImprovementType == GameInfoTypes.IMPROVEMENT_FARM ) then
retval = true;
end
end
return city and plot and retval;
end
Pasted the code in the spoiler below using the (SPOILER)(CODE) code (/SPOILER)(/CODE) in brackets. Hope its makes it easier to read.
--[[ Wandering Wiseman ]]--
function WanderingWisemanCond( player, city, unit, plot )
return city and city:IsCapital() and plot:IsCity();
end
function WanderingWisemanCond1( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
return WanderingWisemanCond( player, city, unit, plot ) and player:GetGold() >= (200 + ncounter*50) ;
end
function WanderingWisemanCond2( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
return WanderingWisemanCond( player, city, unit, plot ) and player:GetGold() >= (100 + ncounter*25) ;
end
function WanderingWisemanNoEffect( player, city, unit, plot )
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT_NONE" ) );
end
function WanderingWisemanEffect1( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
player:ChangeGold( - (200 + ncounter*50) );
_AddNewUnit( player, "UNIT_SCIENTIST", plot:GetX(), plot:GetY() );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT1" ) );
end
function WanderingWisemanEffect2( player, city, unit, plot )
local mera = player:GetCurrentEra();
local mcounter = 0;
if mera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
mcounter = 1;
elseif mera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
mcounter = 2;
elseif mera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
mcounter = 3;
elseif mera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
mcounter = 4;
elseif mera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
mcounter = 5;
elseif mera == GameInfo.Eras[ "ERA_MODERN" ].ID then
mcounter = 6;
else
mcounter = 7;
end
player:ChangeGold ( - (100 + mcounter*25) );
local res = math.random( 0, 99 );
if res < 35 then
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 40;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 70;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 122;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 214;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 375;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 656;
else
ncounter = 1148;
end
player:GetCurrentCultureBonus(ncounter);
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2A" ) );
elseif res < 40 then
player:SetNumFreeTechs( 1 );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2B" ) );
Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH,
Data1 = player,
Data3 = -1
} );
elseif res < 60 then
local tech = player:GetCurrentResearch();
_PlayerSetTech( player, tech, true );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2C" ) );
Events.SerialEventGameMessagePopup( { Type = ButtonPopupTypes.BUTTONPOPUP_CHOOSETECH,
Data1 = player,
Data3 = tech
} );
elseif res < 95 then
local turns = math.random( 2, 4 );
player:ChangeGoldenAgeTurns( turns );
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2D", turns ) );
else
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_WANDERING_WISEMAN_EFFECT2E" ) );
end
end
UserEventAdd{
id = "WANDERING_WISEMAN",
probability = 0.002,
condition = Low_Cond,
this_event_limit = 20;
any_event_limit = 5;
options = {
OPTION_L = { order = 1, condition = WanderingWisemanCond1, effect = WanderingWisemanEffect1, flavor1 = "FLAVOR_GROWTH", flavor2 = "FLAVOR_SCIENCE" },
OPTION_C = { order = 2, condition = WanderingWisemanCond2, effect = WanderingWisemanEffect2, flavor1 = "FLAVOR_SCIENCE", flavor2 = "FLAVOR_SCIENCE" },
OPTION_M = { order = 3, condition = WanderingWisemanCond, effect = WanderingWisemanNoEffect, flavor1 = "FLAVOR_GOLD", flavor2 = "FLAVOR_GROWTH" },
}
};
--[[ / Wandering Wiseman ]]--
--[[ Singer]]--
-- condition function
function SingerCond( player, city, unit, plot )
-- valid only if player has writing and on plots with improvements
return city and _PlayerHasTech( player, "TECH_WRITING") and (plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_MINE" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_FARM" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_IRRIGATION" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_TRADING_POST" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_FP_TRADING_POST" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_QUARRY" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_PASTURE" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_CAMP" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_PLANTATION" ].ID or plot:GetImprovementType() == GameInfo.Improvements[ "IMPROVEMENT_LUMBERMILL" ].ID);
end
--effect function
function SingerEffect( player, city, unit, plot )
local nera = player:GetCurrentEra();
local ncounter = 0;
if nera == GameInfo.Eras[ "ERA_ANCIENT" ].ID then
ncounter = 1;
elseif nera == GameInfo.Eras[ "ERA_CLASSICAL" ].ID then
ncounter = 2;
elseif nera == GameInfo.Eras[ "ERA_MEDIEVAL" ].ID then
ncounter = 3;
elseif nera == GameInfo.Eras[ "ERA_RENAISSANCE" ].ID then
ncounter = 4;
elseif nera == GameInfo.Eras[ "ERA_INDUSTRIAL" ].ID then
ncounter = 5;
elseif nera == GameInfo.Eras[ "ERA_MODERN" ].ID then
ncounter = 6;
else
ncounter = 7;
end
-- add +1 culture per era to the plot
plot:ChangeCulture(ncounter);
_UserEventMessage( Locale.ConvertTextKey( "TXT_KEY_USER_EVENT_SINGER_EFFECT", city:GetName() ) );
end
-- enable the event
UserEventAdd{
id = "SINGER",
probability = 0.002,
options = {
OPTION_L = { order = 1, condition = SingerCond, effect = SingerEffect },
}
};
-- / Singer ]
[/SPOILER]
I keep getting the message that I already uploaded the file to the thread once.
condition = Low_Cond,
The board software works that way. If you want to upload a file with the same name as a previous upload, you have to either remove the original from your earlier post, or change the name. In this case, it doesn't matter; the mod you uploaded had no event logic in it at all. It's just a bunch of XML tweaks that have nothing to do with this topic. So, I'll comment on what you posted above instead.
As I said before, you don't have to name the options OPTION_L, OPTION_C, and so on. Those are MY names for things, because of the alignment system my mod uses. Every event I add has four choices, but obviously you don't have to do the same. More importantly, you can't have a line like
when you don't HAVE anything named "Low_Cond". It's just like the conditions on the individual options, it has to point to a function you've declared in your file.Code:condition = Low_Cond,
Because of this, I can't just rewrite your code for you, because I don't know what you're trying to DO with the features I've added. If there isn't some sort of global condition you want to put on the event, then just don't declare that line. All of the things I wrote into my logic are backwards-compatible; passing in the old-style event declarations will still work just fine, so you only need to declare those extra lines if you want to take advantage of the features they add. The same goes for Flavors; you can have zero, you can have three, you can have any number in between. (And if you want more than three, it's easy enough to patch in.) Don't feel obligated to use two just because I did.
If I understand you correct I could just keep as simple as to mod in your changes (from post 26) in UserEvents.lua and UserEventsPopup.lua?
Optionally I could mod in the flavor part in MyuserEvents.lua to make the AI decide on events based on leader personalities , e.g.
Correct. If you include the changes I made to those two files, all of your existing Event declarations should work exactly the same as before, and the AI would simply pick an outcome at random. You don't have to use those extra bits like the any_event thing if you don't want to.
Right. The AI will weight each option's chances by (X+5)/10, where X is the leader's bias in that particular Flavor. Give multiple flavors (or the same one multiple times), and it'll do this multiplication again for each one.
Note that this is the bias in the DATABASE. The game randomizes each bias slightly at the start of the game, up or down by 0-2, and that shift isn't included. Likewise, if you pick "Randomize Personalities", then it'll still weight the outcomes by what you would have had if you hadn't randomized.
If you're having a hard time getting those changes into the Lua, just go download my Mythology mod and copy directly from my versions of those files. I KNOW those versions work, after all.
Right now I'm in the middle of tracking down why I can't get event with techs as prerequirement to work, i.e. "_PlayerHasTech( player, "TECH_###")".