CustomNotificationPanel.lua -- for easy addition of custom notifications.

I have a question for you Whys: Did you see how the city growth notification is stopped at 5? I haven't found any hints as to a cut-off but, in fact, haven't found how it's triggered, either. So I suspect it's hardcoded
 
Yeah I remember running across it at one point. Don't remember if it was in the xml or lua. I'm leaning lua, but either way, I'm mostly sure it can be modded.

Ok I'll go through it again with a fine comb some time later, then. Thanks
 
I have a slightly different approach to this. You can add the xml data in a new context, then load this context from NotificationPanel and inject the important data via LuaEvent. From my Growth Notifications mod:

NotificationPanel.lua (additions at the end)
Code:
ContextPtr:LoadNewContext("CustomNotification")
LuaEvents.CustomNotificationLoaded(Controls, ProcessStackSizes)

CustomNotification.xml
Code:
<?xml version="1.0" encoding="utf-8"?>

<Context Name="CustomNotification">
	<Instance Name="CityGrowth2Item" >
		<Container Anchor="R,C" Size="80,80" Offset="0,0"  Hidden="0" ID="CityGrowth2Container" ConsumeMouseButton="1" >
			<SlideAnim Anchor="L,T" Style="NotificationSlide" ID="NotificationSlide" >
				<AlphaAnim Style="NewFinger" />
				<Button Anchor="R,C" Size="80,80" Offset="0,0" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" ID="CityGrowth2Button"  Hidden="0" >
					<ShowOnMouseOver>
						<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" />
						<AlphaAnim  Anchor="C,C"  AnchorSide="O.O"  Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameGlow2.dds"  Pause="0" Cycle="Bounce" Speed="1" AlphaStart="1" AlphaEnd="0" Hidden="0"/>
					</ShowOnMouseOver>
					<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationCityGrowth.dds" />
					<AlphaAnim Anchor="C,C" Offset="0,0" Size="80.80"  TextureOffset="0.0" Texture="assets\UI\Art\Notification\NotificationCityGrowthGlow.dds"  Pause="0" Cycle="Bounce" Speed="1" AlphaStart="0" AlphaEnd="1"/>
					<Label Anchor="C,C" Offset="0,0" String="" Font="TwCenMT20" ColorSet="Beige_Black_Alpha" FontStyle="Shadow" ID="CityGrowth2Count" />
				</Button>
			</SlideAnim>
		</Container>
	</Instance>

	<Instance Name="CityTileItem" >
		<Container Anchor="R,C" Size="80,80" Offset="0,0"  Hidden="0" ID="CityTileContainer" ConsumeMouseButton="1" >
			<SlideAnim Anchor="L,T" Style="NotificationSlide" ID="NotificationSlide" >
				<AlphaAnim Style="NewFinger" />
				<Button Anchor="C,C" Size="80,80" Offset="0,0" Texture="assets\UI\Art\Notification\NotificationClearBase.dds" ID="CityTileButton"  Hidden="0" >
					<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationTileFrame.dds" />
					<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationTileGlass.dds" />
					<AlphaAnim Anchor="C,C" Offset="0,0" Size="80.80"  TextureOffset="0.0" Texture="assets\UI\Art\Notification\NotificationTileGlow.dds"  Pause="0" Cycle="Bounce" Speed="1" AlphaStart="0" AlphaEnd="1"/>
					<Label Anchor="C,C" Offset="0,0" String="" Font="TwCenMT20" ColorSet="Beige_Black_Alpha" FontStyle="Shadow" ID="CityTileCount" />
				</Button>
			</SlideAnim>
		</Container>
	</Instance>
</Context>


CustomNotification.lua
Code:
--[[
	CustomNotification.lua
	Creator: alpaca
	Last Change: 28.11.2010
	
	Description: Adds support for the city growth and culture tile spread notifications to the game
]]--

include("lib")

customNotifications = {}
customInstances = {}
nextID = 1

function addCustomNotification(noty)
	customNotifications[nextID] = noty
	noty.ID = nextID
	nextID = nextID + 1
end



------------------------------------------------------------------
--	Notification class
------------------------------------------------------------------
Notification = class(
	function(o, name, summary, toolTip, leftClick, rightClick)
		o.Name = name
		o.Instance = nil
		o.Summary = summary
		o.ToolTip = toolTip
	end
)

--[[
	Gets the instance of this notification
	Returns:
		instance
]]--
function Notification:GetInstance()
	if self.Instance == nil then
		self.Instance = {}
		ContextPtr:BuildInstanceForControl( self.Name.."Item", self.Instance, Controls.SmallStack );
	end
	return self.Instance
end

function Notification.LeftClick(id)
	return
end

function Notification.RightClick(id)
	customNotifications[id]:Remove()
end

function Notification:Show()
	addCustomNotification(self)
	local container = self:GetInstance()[self.Name.."Container"]
	local button = self:GetInstance()[self.Name.."Button"]
	self:GetInstance().FingerTitle:SetText( self.Summary )
	container:BranchResetAnimation();

	button:SetHide(false)
	button:SetVoid1(self.ID)
	button:RegisterCallback(Mouse.eLClick, self.LeftClick)
	--button:RegisterCallback(Mouse.eRClick, testClick)
	button:RegisterCallback(Mouse.eRClick, self.RightClick)
	button:SetToolTipString(self.ToolTip)

	ProcessStackSizes();
end

function Notification:Remove()
	Controls.SmallStack:ReleaseChild( self:GetInstance()[self.Name.."Container"] )
	customNotifications[self.ID] = nil
	ProcessStackSizes()
end

------------------------------------------------------------------
--	CityZoomNotification class
------------------------------------------------------------------

CityZoomNotification = class(Notification, 
	function (o, name, summary, toolTip, plot)
		o.Plot = plot
		Notification.init(o, name, summary, toolTip)
	end
)

function CityZoomNotification.LeftClick(id)
	local self = customNotifications[id]
	UI.DoSelectCityAtPlot(self.Plot)
	ProcessStackSizes();
end

------------------------------------------------------------------
--	Event handling
------------------------------------------------------------------

------------------------------------------------------------------
--	City Growth notification (also above pop 5)
------------------------------------------------------------------

-- initialise city sizes
citySizes = {}

for pCity in Players[Game.GetActivePlayer()]:Cities() do
	citySizes[pCity:GetID()] = pCity:GetPopulation()
end

--[[
	Detects city growth and fires a notification
]]--
function CityGrowthNotificationOnActivePlayerTurnStart()
	for pCity in Players[Game.GetActivePlayer()]:Cities() do
		local newPop = pCity:GetPopulation()
		print("Checking population: new pop is "..tostring(newPop)..", old pop is "..tostring(citySizes[pCity:GetID()]))
		if citySizes[pCity:GetID()] == nil then
			citySizes[pCity:GetID()] = newPop
		else
			if newPop ~= citySizes[pCity:GetID()] then
				citySizes[pCity:GetID()] = newPop
				local pPlot = pCity:Plot()
				notification = CityZoomNotification("CityGrowth2", Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_SUMMARY_CITY_GROWTH_2", pCity:GetName()), Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_CITY_GROWTH_2", pCity:GetName(), newPop), pPlot)
				notification:Show()
			end
		end
	end
end
Events.ActivePlayerTurnStart.Add(CityGrowthNotificationOnActivePlayerTurnStart)


------------------------------------------------------------------
--	Border Growth notification
------------------------------------------------------------------
-- initialise culture levels
cityCultureLevels = {}

for pCity in Players[Game.GetActivePlayer()]:Cities() do
	cityCultureLevels[pCity:GetID()] = pCity:GetJONSCultureLevel()
end

--[[
	Detects city growth and fires a notification
]]--
function CultureLevelNotificationOnActivePlayerTurnStart()
	for pCity in Players[Game.GetActivePlayer()]:Cities() do
		local newLevel = pCity:GetJONSCultureLevel()
		if cityCultureLevels[pCity:GetID()] == nil then
			cityCultureLevels[pCity:GetID()] = newLevel
		else
			if newLevel ~= cityCultureLevels[pCity:GetID()] then
				cityCultureLevels[pCity:GetID()] = newLevel
				local pPlot = pCity:Plot()
				notification = CityZoomNotification("CityTile", Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_SUMMARY_CITY_TILE", pCity:GetName()), Locale.ConvertTextKey("TXT_KEY_NOTIFICATION_CITY_TILE", pCity:GetName()), pPlot)
				notification:Show()
			end
		end
	end
end
Events.ActivePlayerTurnStart.Add(CultureLevelNotificationOnActivePlayerTurnStart)


------------------------------------------------------------------
--  Overhead
------------------------------------------------------------------

function OnTurnEnd()
	for id, pNotification in pairs(customNotifications) do 
		pNotification:RightClick() 
	end
end
Events.ActivePlayerTurnEnd.Add(OnTurnEnd)

function OnCustomNotificationsLoaded(controls, processStackSizes)
	Controls = controls
	ProcessStackSizes = processStackSizes
end

LuaEvents.CustomNotificationLoaded.Add(OnCustomNotificationsLoaded)

This needs

lib.lua
Code:
--[[
	lib.lua
	
	Creator: alpaca
	Last Change: 27.11.2010
	
	Description: Adds some useful functions
]]--

-- Constants

MAX_LOGGING_DEPTH = 10
SPACES_PER_TAB = 4

--[[
	Recursively prints a table. For userdata, the metatable is logged
	Arguments:
		tab: Table. Table to log
		depth: Number. Current depth (for recursion)
		maxDepth: Number. Maximal recursion depth (to avoid infinite loops through back-referencing)
		callStack: Used internally
	Returns:
		true: on success
]]--
function printTable(tab, depth, maxDepth, callStack)
	local depth = depth or 0
	local maxDepth = maxDepth or MAX_LOGGING_DEPTH
	local iD = iD or "default"
	local callStack = callStack or {}
	
	if tab == nil then
		print(intToSpaces(depth).."<nil>")
		return 
	end
	if tab == {} then
		print(intToSpaces(depth).."<empty>")
		return
	end
	
	if depth > maxDepth then
		return "MaxDepth reached"
	end
	
	tab = (type(tab) == "userdata") and getmetatable(tab) or tab -- for userdata, we use the metatable
	
	for k,v in pairs(tab) do
		if type(v) == "table" then
			print(intToSpaces(depth).."(table) "..tostring(k))
			-- avoid infinite recursion by making sure the table is only printed once
			if callStack[v] == nil then
				callStack[v] = v
				printTable(v, depth + 1, maxDepth, iD, callStack)
			end
		else
			print(intToSpaces(depth).."("..type(k)..") "..tostring(k)..": ".."("..type(v)..") "..tostring(v))
		end
	end
end


--[[
	Converts an integer into a string containing n times so many spaces (for indentation).
	Arguments:
		num: Number. Number of "tabs" to write
	Returns:
		String containing the spaces
]]--
function intToSpaces(num)
	local retValue = ""
	for var = 1, num*SPACES_PER_TAB do
		retValue = retValue.." "
	end
	return retValue
end


--[[
	Defines a class that can be instantiated. Taken from the LuA users wiki: http://lua-users.org/wiki/SimpleLuaClasses (April 8th 2010)
	An example for implementing a class with this can be found in the wiki.
	Arguments:
		base: Class. Base class to derive this class from
		init: Function. Initialisation function to call - a constructor if you will
	Returns:
		The class object
]]--
function class(base, init)
	local c = {}    -- a new class instance
	if not init and type(base) == 'function' then
		init = base
		base = nil
	elseif type(base) == 'table' then
		-- our new class is a shallow copy of the base class!
		for i,v in pairs(base) do
			c[i] = v
		end
		c._base = base
	end
	-- the class will be the metatable for all its objects,
	-- and they will look up their methods in it.
	c.__index = c

   -- expose a constructor which can be called by <classname>(<args>)
	local mt = {}
	mt.__call = function(class_tbl, ...)
		local obj = {}
		setmetatable(obj,c)
		
		if init then
			init(obj,...)
		else 
			-- make sure that any stuff from the base class is initialized!
			if base and base.init then
				base.init(obj, ...)
			end
		end
		return obj
	end
	
	c.init = init
	c.is_a = function(self, klass)
		local m = getmetatable(self)
		while m do 
			if m == klass then return true end
			m = m._base
		end
		return false
   end
   setmetatable(c, mt)
   return c
end

and the text strings

Code:
<?xml version="1.0" encoding="utf-8"?>
<!-- Created by ModBuddy on 11/28/2010 5:33:32 PM -->
<GameData>
	<Language_en_US>
		<Row Tag="TXT_KEY_NOTIFICATION_CITY_GROWTH_2">
			<Text>The City of {1_CityName} now has {2_Pop} [ICON_CITIZEN] Citizens! The new Citizen will automatically work the land near the City for additional [ICON_FOOD] Food, [ICON_PRODUCTION] Production or [ICON_GOLD] Gold.[NEWLINE][NEWLINE]Click on this message to open its city view.</Text>
		</Row>
		<Row Tag="TXT_KEY_NOTIFICATION_SUMMARY_CITY_GROWTH_2">
			<Text>{1_CityName} has grown!</Text>
		</Row>
		<Row Tag="TXT_KEY_NOTIFICATION_CITY_TILE">
			<Text>The City of {1_CityName} has claimed a new tile for [ICON_CITIZEN] to work on![NEWLINE][NEWLINE]Click on this message to open its city view.</Text>
		</Row>
		<Row Tag="TXT_KEY_NOTIFICATION_SUMMARY_CITY_TILE">
			<Text>{1_CityName} has claimed a new tile!</Text>
		</Row>
	</Language_en_US>
</GameData>
 
I'm getting an error, "attempt to index field FingerTitle (a nil value)" on line 83 of CustomNotificationPanel.lua.

I read this thread for the first time. if you still have problem then the cause of this problem is the following:
Code:
LuaEvents.CustomNotification(1003,
[B][COLOR="Red"]"City-State Captured"[/COLOR][/B],
"Looted food supplies from a captured Maritime city-state allowed your Capital to gain 1 citizen.",
{ location={pPlot:GetX(), pPlot:GetY()} }
);

the text in Red must be same name of your Instance name without "Item", for example in NotificationPanel.XML if you use:

Code:
<Instance Name="CityStateItem" >

then use :
Code:
LuaEvents.CustomNotification(ID,[B][COLOR="Red"] "CityState" [/COLOR][/B], "Tooltip text" , location
);

EDIT: Actually after testing CustomNotificationPanel.lua it doesnt matter you can use any text. I was using another version of CustomNotification from someone else thats why it is not same case here.
 
I read this thread for the first time. if you still have problem then the cause of this problem is the following:

Actually, it's more than that. There was a problem created in the December megapatch where the old version of this mod would give that error every time, even if the titles were handled correctly.
The problem was the VFS change. To get this to work, you have to set the VFS to true (for all three files) and NOT add the Lua through the usual InGameUIAddIn or InGame.xml methods. At that point it should work fine.
 
Actually, it's more than that. There was a problem created in the December megapatch where the old version of this mod would give that error every time, even if the titles were handled correctly.
The problem was the VFS change. To get this to work, you have to set the VFS to true (for all three files) and NOT add the Lua through the usual InGameUIAddIn or InGame.xml methods. At that point it should work fine.

Yup this was the actual problem, the problem that I refereed to earlier was with another CustomNotification from someone else I mixed up between them.
 
Hello,
first of all thanks for this util!
Since i want to use it in a mod i found it annoying that it modifies the vanilla notificationpanel files. Thanks to the insights from Onni, I'll post here my solution (in case it wasn't posted anywhere yet).

These files are some snippets from my soon-to-be-published mod. Since they are modified for this post, I can not guarantee that this code will work.

Ingredients:
mainfile.lua, mainfile.xml
CCxNotifications.lua CCNotifications.xml (!These two files need to have different Filenames!)
Set mainfile.lua as InGameUIAddin and import all files into the VFS.

------------------
First the XML files:

mainfile.xml
Code:
<!-- mainfile.xml -->

<?xml version="1.0" encoding="utf-8"?>
<!-- Author: Moaf -->
<Context>
	<LuaContext FileName="CCNotifications" ID="CCNotifications" Hidden="1" />
</Context>
The LuaContext points to CCNotifications; but since there is no CCNotifications.lua you'll get an error message (which you can ignore).


CCNotifications.xml
Code:
<!-- CCNotifications.xml -->

<?xml version="1.0" encoding="utf-8"?>
<!-- Author: Moaf -->
<Context>
	<!--=======================================================================================================================-->
	<!-- Cultural Capital Notification -->
	<!--=======================================================================================================================-->
	<Instance Name="CCItem" >
		<Container Anchor="R,C" Size="80,80" Offset="0,0"  Hidden="0" ID="CCContainer" ConsumeMouseButton="1" >
			<SlideAnim Anchor="L,T" Style="NotificationSlide" ID="NotificationSlide" >
				<AlphaAnim Style="NewFinger" />
				<Button Anchor="R,C" Size="80,80" Offset="0,0" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" ID="CCButton"  Hidden="0" >

					<ShowOnMouseOver>
						<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameBase.dds" />
						<AlphaAnim  Anchor="C,C"  AnchorSide="O.O"  Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationFrameGlow2.dds"  Pause="0" Cycle="Bounce" Speed="1" AlphaStart="1" AlphaEnd="0" Hidden="0" />
					</ShowOnMouseOver>
					<Image Anchor="C,C" Offset="0,0" Size="80,80" Texture="assets\UI\Art\Notification\NotificationBlack.dds" />
					<AlphaAnim Anchor="C,C" Offset="0,-1" Size="80,80" Texture="assets\UI\Art\Notification\SocialPolicyActive80.dds" ID="CCImage"  Pause="0" Cycle="Bounce" Speed="1" AlphaStart=".5" AlphaEnd="1" />
					<FlipAnim Size="64,64" Offset="0,6" Anchor="C,C" Columns="8" Speed="20" Pause=".5" StepSize="64,64" FrameCount="31" Texture="assets\UI\Art\Notification\CapitalAnimation.dds" />
					<Label Anchor="C,C" Offset="0,0" String="" Font="TwCenMT20" ColorSet="Beige_Black_Alpha" FontStyle="Shadow" ID="CCCount" />
				</Button>

			</SlideAnim>
		</Container>
	</Instance>
</Context>

------------------
Now the LUA files:

mainfile.lua
Code:
-- mainfile.lua

import("CCxNotifications");

function OnLoadScreenClose()
  CCNot_Init();
end
Events.LoadScreenClose.Add(OnLoadScreenClose);
Just calls the Initializer function in the CCxNotifications.lua file when the player starts the game.


CCxNotifications.lua
Code:
include("MoafsUtils");
include("FLuaVector");
include( "WhysUtils" );
-- vymdt.01.2010.11.12.1515
-- Created by: Whys Alives, modified by Moaf
--===========================================================================
--[[
Global Variables.
]]
local g_customActiveNotifications  = {};
local g_customInstances            = {};
local g_customData                 = {};
local g_customId                   = 0;

--handled custom notification types.
local g_customNameTable = {};
g_customNameTable[GameInfo.CCNotifications.NOTIFICATION_CULTURALCAPITAL] = "CC";

--===========================================================================
--===========================================================================
--===========================================================================
-------------------------------------------------------------------------------
-- details for dynamically sizing the small notification stack, copied from notificationpanel.lua
-------------------------------------------------------------------------------
local DIPLO_SIZE_GUESS = 120;
local _, screenY = UIManager:GetScreenSizeVal();
local offsetY;
local g_SmallScrollMax;

-- Init function
function CCNot_Init()
	print("CCNot_Init");
	local context = ContextPtr:LookUpControl("../CCNotifications/");
	context:ChangeParent(ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/"));
  _, offsetY = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/OuterStack"):GetOffsetVal();
	g_SmallScrollMax = screenY - offsetY - DIPLO_SIZE_GUESS;
end
-------------------------------------------------
-------------------------------------------------
-- copied and modified from notificationpanel.lua
function CCNot_ProcessStackSizes()
	local smallStack = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/SmallStack");
	local smallScrollPanel = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/SmallScrollPanel");
	local bigStack = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/BigStack");
	local outerStack = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/OuterStack");

  bigStack:CalculateSize();
  local bigY = bigStack:GetSizeY();
  smallScrollPanel:SetSizeY( g_SmallScrollMax - bigY );
  smallStack:CalculateSize();
  smallStack:ReprocessAnchoring();
	smallScrollPanel:CalculateInternalSize();
  if( smallScrollPanel:GetRatio() ~= 1 ) then
      smallScrollPanel:SetOffsetVal( 20, 0 );
  else
      smallScrollPanel:SetOffsetVal( 0, 0 );
  end
    
  outerStack:CalculateSize();
  outerStack:ReprocessAnchoring();
end
--===========================================================================
--===========================================================================
--===========================================================================
--[[
handles default mouse left-click for custom notifications.  Uses fourth
argument in LuaEvents.CustomNotification() to goto {x,y} map location.
]]
function CCNot_CustomLeftClick( id )
  if  type( g_customData[id] ) == "table" and
      type( g_customData[id]["location"] ) == "table" then
    local plot = Map.GetPlot( g_customData[id]["location"][1]
        , g_customData[id]["location"][2] );
    if plot ~= nil then
			UI.LookAt( plot, 0 );
			Events.SerialEventHexHighlight(ToHexFromGrid(Vector2(plot:GetX(), plot:GetY())), true, Vector4(1.0, 0.0, 1.0, 1.0));
		end
  end
end
--===========================================================================
--[[
handles default mouse right-click for custom notifications.  Deactivates
custom notification.
]]
function CCNot_CustomRightClick( id )
  if g_customActiveNotifications[id] == nil then
    print("Unknown Custom Notification Id: "..tostring(id));
		return;
  end
  local name = g_customNameTable[g_customActiveNotifications[id]];
  local instance = g_customInstances[id];
  if instance ~= nil then
		local smallStack = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/SmallStack");
    smallStack:ReleaseChild( instance[name.."Container"] );
    g_customInstances[id] = nil;
  end
  CCNot_ProcessStackSizes();
end
--===========================================================================
--===========================================================================
function CCNot_OpenCCInfoOnLeftClick(id)
  CCNot_CustomLeftClick(id);
end
--===========================================================================
--[[
Activates custom notification.
]]
function CCNot_OnCustomNotificationAdded( iType, summary, toolTip, data )
	
	local smallStack = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/SmallStack");
	local notificationPanelContext = ContextPtr:LookUpControl("/InGame/WorldView/ActionInfoPanel/NotificationPanel/");
	local ccNotContext = ContextPtr:LookUpControl("../CCNotifications/");

  g_customId = g_customId + 1;
  if g_customActiveNotifications[g_customId] ~= nil then
    print("Redundant Custom Notification Type: "..tostring(iType));
		return;
  end
  local instance = {};
  local name = g_customNameTable[iType];

	ccNotContext:BuildInstanceForControl(name.."Item", instance, smallStack);
  g_customInstances[g_customId]  = instance;
  g_customData[g_customId] = data;

  local root   = instance[name.."Container"];
  local button = instance[name.."Button"];

  instance.FingerTitle:SetText( summary );
  root:BranchResetAnimation();

  local leftClick, rightClick = nil, nil;
  --.........................................................................
  -- Custom Notification Handling
  if iType == GameInfo.CCNotifications.NOTIFICATION_CULTURALCAPITAL then
    leftClick = CCNot_OpenCCInfoOnLeftClick;
  end
  --END Custom Notification Handling
  --.........................................................................
  if type( leftClick  ) ~= "function" then leftClick  = CCNot_CustomLeftClick;  end
  if type( rightClick ) ~= "function" then rightClick = CCNot_CustomRightClick; end

  button:SetHide( false );
  button:SetVoid1( g_customId );
  button:RegisterCallback( Mouse.eLClick, leftClick );
  button:RegisterCallback( Mouse.eRClick, rightClick );
  button:SetToolTipString( toolTip );

  g_customActiveNotifications[g_customId] = iType;
  CCNot_ProcessStackSizes();
end
LuaEvents.CustomNotification.Add( CCNot_OnCustomNotificationAdded );
--===========================================================================
--[[
Deactivates all custom notifications on end of turn.
]]
function CCNot_OnTurnEnd()
  for id,type in pairs(g_customInstances) do CCNot_CustomRightClick(id); end
end
Events.ActivePlayerTurnEnd.Add(CCNot_OnTurnEnd);
In the CCNot_Init() function we find the Context by qualifying ContextPtr:LookUpControl("../CCNotifications").
Then we reset its parent to the NotificationStack which can be found in "/InGame/WorldView/ActionInfoPanel/NotificationPanel/".
Since we need to resize and reprocess the stack when an element gets added to it, and since we have no access to the ProcessStackSizes() function in the NotificationPanel.lua file, I've copied the function(and necessary properties) and modified it so we can reprocess the controls.
Additionally, any function that uses any control from NotificationPanel must be modified to look up the corresponding control.

I hope I haven't forgotten anything :)
 
Interesting. How do you load CCxNotifications.lua?
 
I have added a FULLY MODIFIABLE custom notification addin method here:
Fully Modifiable Custom Notifications

This requires only adding 3 files, and creating a NotificationAddin for your mod. It does not need to overwrite NotificationPanel.xml at all.

On top of that, it allows added functionality of highlighting plots, zooming in on plots, entering city screens, hooking up icons from icon atlases, and pretty much doing whatever it is you need your notification to do.
 
Moaf, for your version, wouldn't each version of this utility being run cause duplicates of the CustomNotification LuaEvent? More than one mod using this at once would cause each trigger to run every single Add.
 
Hm, maybe it is possible to run the mainfile.lua as a UIAddin in an own independent mod, which offers LuaEvents to add/trigger custom notifications?
 
Top Bottom