1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

A couple more "quick" inquiries

Discussion in 'Civ5 - Creation & Customization' started by AW Arcaeca, Dec 7, 2014.

  1. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,969
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    1. Is it possible to add a new civilopedia section, preferably without having to edit the civiliopedia.lua file?

    2. Is there an event-hook - seeing as how I haven't been able to find one - which fires when a city is captured? I'm aware of GameEvents.CityCaptureComplete, but I need it fire the same turn the city is captured, not when resistance ends, which, IINM is what that event hook listens for.

    3. Is it possible, without DLL, to make a city literally impossible for an enemy to take over? There's always simply giving the city a dummy building with an extraordinarily high <Defense> and/or <CityHitPoints> (if that's what it's called, I don't exactly remember) value, but even that will eventually give out to superior military might. I suppose, if a game event such as described in #2 can be found, one could make some lua that would instantly return the city to its original owner...?

    4. Possible to detect if a city is next to a lake with lua? I can imagine using the <Traits> FreeBuilding column to give a dummy to all cities conditional that they meet the geographic constraint of being by a lake (which would theoretically work since FreeBuilding at least checks for geographic constraints - it doesn't give Carthage harbors in landlocked cities - and I could use the column from the floating gardens), but frankly I'm sure there's a less involved way with lua, probably involving PlotIterators to sweep through all tiles adjacent to a city and seeing if at least one is water.

    5. Does City.GetGarrisonedUnit work with a civilian unit? I've got a civ in progress with a civilian UU which will have a unique effect on cities as long as it's stationed in one, but I can't figure out whether to use this method or a workaround. Perhaps something like "if (pUnit:GetPlot() == pCity:GetPlot()) then"?

    6. A game event, or really any method, that fires when a civilian unit is captured: Does such a think exist? I'm really in the dark for this one; I can't find or even imagine any method of this ilk existing and I can't think of any workaround.

    If I can think of any more questions in the near future, hopefully I'll remember to just add them to this thread.

    TIA,
    AW
     
  2. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    #2 is incorrect to the best of my knowledge. I use CityCaptureComplete in my Civ to handle resource yield reset functions when a City is taken. This function is run as soon as the City has been taken. It even fires when a City is traded to another player -- the bConquest boolean would return false in this case, I believe.

    #3 I wonder if you might be able to just use Lua to reset the City's hitpoints to maximum after every attack, or something.

    #4 you can use PlotIterators to iterate the tiles immediately around a City and test for plot:IsLake() I think.

    No idea on 1, 5 and 6 off the top of my head. Mainly wanted to respond to #2.
     
  3. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,969
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    Ah, well then, that simplifies things. :)
    EDIT: Oh, and related - Basically, the idea in mind is that when Civ X's cities are captured, they're obliterated rather than fall to the enemy. But I'm trying to find a function for obliterating a city, like InitCity but the opposite. There's Player.Raze() but would that start the razing process or, as I would prefer, immediately eliminate the city?

    But as for #3, resetting hitpoints after every attack would probably work, but the only combat-related game events I'm aware of that fire on/after an attack and don't deal with the graphics engine (e.g. GameEvents.CombatSimEnded) are RED events. :/

    The PlotIterator method makes me wonder how much of this code from JFD's Carthage can be recycled to suit my purposes...
    Spoiler :
    Code:
    iResource = GameInfoTypes.RESOURCE_JFD_SHELLFISH
    iRadius = 3
    
    function Sukritact_PlaceResource(pCity)
        local pPlot = pCity:Plot()
        local tPlots = {}
        local iNumtoPlace = 1
        for pLoopPlot in PlotAreaSweepIterator(pPlot, iRadius, SECTOR_NORTH, DIRECTION_CLOCKWISE, DIRECTION_OUTWARDS, CENTRE_EXCLUDE) do
            table.insert(tPlots, pLoopPlot)
        end
    	
        for iVal = 1, iNumtoPlace do
    		local bPlaced = false
    		while (not(bPlaced)) and #tPlots > 0 do
    			local iRandom = GetRandom(1, #tPlots)
    			local pPlot = tPlots[iRandom]
    			if pPlot:GetTerrainType() == GameInfoTypes["TERRAIN_COAST"] and pPlot:GetFeatureType() ~= GameInfoTypes["FEATURE_ATOLL"] and not pPlot:IsLake() and pPlot:GetResourceType() == -1 then
    				pPlot:SetResourceType(iResource, 1)
    				bPlaced = true
    			end
    			
    			table.remove(tPlots, iRandom)
    		end
    	end
    end

    Obviously not exactly the same, but what if we edited it so...
    Spoiler :
    Code:
    iRadius = 1
    
    function CheckForLake(pCity)
        local pPlot = pCity:Plot()
        local tPlots = {}
        local iNumtoPlace = 1
        for pLoopPlot in PlotAreaSweepIterator(pPlot, iRadius, SECTOR_NORTH, DIRECTION_CLOCKWISE, DIRECTION_OUTWARDS, CENTRE_EXCLUDE) do
            table.insert(tPlots, pLoopPlot)
        end
    	
        for iVal = 1, iNumtoPlace do
    		while #tPlots > 0 do
    			local iRandom = math.rand(1, #tPlots)
    			local pPlot = tPlots[iRandom]
    			if pPlot:IsLake() then
    				return true
    			end
    			
    			table.remove(tPlots, iRandom)
    		end
    	end
    end

    I'm not exactly the most well-versed with PlotIterators. :lol: Seeing as how I've never needed to use it before. But the idea here ^ is that it the function will now iterate around all plots 1 tile from a city and stop and return true once it finds one that is a lake.
     
  4. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    The main thing is that it seems like we all use whoward's PlotIterators file, hence the call to "PlotAreaSweepIterator()", though I use "PlotAreaSpiralIterator()" myself.

    The problem I have with the above code is that it's needlessly complicated if you're only doing the one check. Why bother storing the plots in a table when you're only going to then check it once and remove it if it doesn't have what you want?

    My Civ's NewCityResources() function scans all plots 1-tile around the founding of a new city looking for specific resources using whoward's PlotAreaSpiralIterator() and does the check in real-time. The gist of it is that you just feed it the pPlot of whatever plot your City is on, then tell it to scan a 1-plot radius, and for each plot (pLoopPlot in above code) to check for a lake (pLoopPlot:IsLake()) and if it is, then you can either store that plot or do what you want, and move on.

    Additionally, after those plots are stored in the table, he goes testing entries in the table randomly? Perhaps he has a reason for doing so, but your situation certainly does not call for that.

    Edit:
    I only just noticed and read your edit.
    According to what whoward told me last timed I asked about it, Player.Raze() simply razes the City. I don't remember if it initiated a normal raze, or an immediate raze. I suppose it would be trivial to test with Firetuner, so if you want, I can test it in about half an hour and report back with the results.
     
  5. AW Arcaeca

    AW Arcaeca Deus Vult

    Joined:
    Mar 10, 2013
    Messages:
    2,969
    Gender:
    Male
    Location:
    Operation Padlock ground zero
    Is the NewCityResources function particularly long? If not, may I politely request you to post it? I avoid Steam Workshop like the plague and as for the alternate download links, I seem to have trouble downloading a file from a website apparently from Uganda.
     
  6. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    LOL Uganda.
    I guess that's what the *.ug domain stands for. They probably picked it up for their URL shortener thing, but my alternate downloads are hosted on Pogoplug.com.

    In any case, that function is actually quite long because of all the checks I need to do (and it also refers to some sub-functions I abstracted out) so I wouldn't suggest you try to copy/paste it either; it's more for reference as to how I am using the Plot Iterator.

    I'll hop in the game now to check on the Raze() method for you, and I suppose I can write up a quick condensed version of my function for your needs, although I'm not entirely sure what exactly you're aiming to do with it.
     
  7. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    Okay, just tested the method.
    It appears to not be what you are looking for. All it seems to do is initiate the razing of a City, and furthermore, is limited to only Cities which you could normally raze anyway. In effect, the Lua method is a way to "Press the Raze button" in Lua. Or I guess more accurately, the button calls this Lua method.

    It won't work on your Capital, any Cities you found, enemy Capitals and City-States.

    As far as the Plot Iterator stuff, I don't know what information you have to work with, or what your starting point is, so I will make 2 assumptions:
    1) You've got whoward's PlotIterators.lua installed and properly include()'d into your main Lua file.
    2) You're starting the check on the founding of a new City using GameEvents.PlayerCityFounded().

    Code:
    local function IsNewCityAdjacentToLake(iPlayer, iX, iY)
    	--Check for player civ and stuff if you want, that's what you can use iPlayer for.
    	--Skipping that for this example.
    	local pPlot = Map.GetPlot(iX, iY)
    	local iRadius = 1
    	local sStartSector = SECTOR_NORTH
    	local sDirection = DIRECTION_ANTICLOCKWISE
    	local sFlow = DIRECTION_OUTWARDS
    	local bCenter = CENTRE_EXCLUDE
    	for pAreaPlot in PlotAreaSpiralIterator(pPlot, iRadius, sStartSector, sDirection, sFlow, bCenter) do
    		--Checking to make sure the plot exists first.
    		--Could also insert a check for plot owner, but skipped for this example.
    		if pAreaPlot and pAreaPlot:IsLake() do
    			--It's a lake! DO STUFF! CELEBRATE!
    			--We're done.
    			break
    		end
    	end
    end
    GameEvents.PlayerCityFounded.Add(IsNewCityAdjacentToLake)
    It's essentially exactly the same as above, except I'm not doing what I feel is unnecessary for the task: Adding the plots to a table temporarily only to remove them immediately afterward.
    I also included a 'break' in the loop since it sounds like you only wanted to check for the presence of a Lake at all. If you instead have effects you want to do for every Lake plot adjacent to the City, you'll need to remove the 'break' so that it will continue running the loop until it finishes.

    Edit:
    Reading that code more carefully, I think I understand why JFD used a random element in that scenario. He's trying to place a new resource on a random plot, thus he needs to scan all available plots first, and then choose one randomly.

    Edit2:
    In light of your reported inability to download from Uganda, I've gone ahead and replaced the download links in my thread with their un-shortened versions pointing to pogoplug.com -- can you please verify that they work for you now? I'd imagine if you have problems, you probably won't be the only one.
     
  8. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    For adjacent-plot iteration you can simply do this (assuming you already got pPlot defined somewhere):

    Code:
    for direction = 0, DirectionTypes.NUM_DIRECTION_TYPES - 1, 1 do
    	local pAdjacentPlot = Map.PlotDirection(pPlot:GetX(), pPlot:GetY(), direction)
    	if pAdjacentPlot and pAdjacentPlot:IsLake() then 
    		--Stuff
    	end
    end
    
     
  9. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    That's probably a more direct way, without having to rely on whoward's functions, but his does have the option of being easily adjusted to scan out to a range of 2 or 3 if desired. Both should work.

    I should also mention that there does exist the City:Kill() method that does appear to instantly destroy/raze a City, but it seems to leave behind some graphical bugs.
     
  10. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    Yes yes, it only works for adjacent-plot iteration, it is fairly simple and clean.
    If you want anything else, look elsewhere. hahaha :lol:

    Care to expand? I'm curious. :crazyeye:
     
  11. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    I tend to use whoward's function simply because it lets me be lazier and just define a radius for each type of plot-scan I need done (and my Civ has a lot of plot scanning to do each turn, and even mid-turn.)

    The downside is that, well, you do have to rely on someone else's functions (even if they are whoward,) and as I found out the hard way, a certain Really Advanced Setup mod tends to completely screw it up because of the way the guy named his files.

    The City will instantly appear to become the "city ruins" graphic, and disappear from all available interaction, but the City's banner will remain for whatever reason, obstructing view of the map and doing nothing but generate Lua errors (because you're trying to access nil) whenever you click on it.
     
  12. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    Woah. That's interesting, I did not know that. :|
    Can you replicate this error? The only code I have that kills a city is done in turn 0, maybe the error comes due to some memory glitch? A conflict perhaps?
     
  13. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    The problem most likely comes due to the game not properly updating the screen when City:Kill() is used on its own. I've replicated many times, which is why I can say so with confidence; I generally try to test everything I suggest, and will explicitly say so (or along the lines of 'I think...') when I am unsure.

    As to why it works for you when you kill them on turn 0, I suspect this is because on turn 0, no one has founded their Cities yet. Everyone is still a settler on turn 0 (at least the start of it.) If you are killing them after they found their cities on turn 0, then I have another hypothesis.

    I suspect this has to do with the City Banner being displayed, as I alluded to above.

    When you try to click on the leftover banner of a city that's been "killed" in this way, you get an error pointing to CityBannerManager.lua. If you are able to kill Cities without issue on turn 0, I assume this is because on turn 0, you have not actually discovered any of these other Cities yet, so there was no city banner displayed to begin with.
     
  14. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    Very good information here.
    I'll have to pay attention to my code then, I'll make the AI play some games and try to find out some workaround.
     
  15. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    Well, I'm curious what exactly you're doing to those poor Cities that require them to be killed off on turn 0, haha.

    But yeah, I generally watch Firetuner for the lua log like a hawk these days.
     
  16. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    A-ha.
    I use 'pPlayer:Disband(pCity)' instead of 'pCity:Kill()'. Maybe that's the reason I do not incur in this graphical issue.

    It's from a mod I'm making for a while now, Geiseric's Civilization; you play as a second Barbarian Civ, but any city you take is automatically razed (both a boon and hindrance).
     
  17. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    Ah, I see. Maybe that method has more cleanup coded in than City:Kill().

    Either way, I feel bad semi-derailing AW's thread, so I'll not investigate further, haha.
     
  18. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    With that in mind... here is your #3 inquiry, AW:
    Code:
    include("FLuaVector.lua") [COLOR="green"]--may remove this and the 'extra' lines if you don't want a nice human reminder that the city is unconquerable[/COLOR]
    
    function NoConquer(iPlayer, iCityID, iDamage, iPreviousDamage)
    	local pPlayer = Players[iPlayer]
    	local pCity = pPlayer:GetCityByID(iCityID)
    	if pPlayer:GetCivilizationType() == [COLOR="Blue"]yourciv[/COLOR] then
    		local pPlot = pCity:Plot()
    		pCity:ChangeDamage(iPreviousDamage - iDamage)
    		[COLOR="Green"]--next 3 lines are 'extra'[/COLOR]
    		if pPlot:IsVisibleToWatchingHuman() then
    			Events.AddPopupTextEvent(HexToWorld(ToHexFromGrid(Vector2(pPlot:GetX(), pPlot:GetY()))), "[COLOR_NEGATIVE_TEXT][COLOR="red"]IMMORTAL H4x0r CITY![/COLOR][ENDCOLOR]", 0)
    		end
    	end
    end
    
    Events.SerialEventCitySetDamage.Add(NoConquer)
    I'm not sure if it is able to avoid complete capture, so just to be sure, set the City's HP veeeeeeeeeeeeery high, so no 1 attack is capable of taking.
    On the other hand, you could test it and return with the answer. :)

    #5: The workaround would certainly works, I don't know about the method though.
    #6: WHoward has a hook for that in his DLL.
     
  19. DarkScythe

    DarkScythe Hunkalicious Holo

    Joined:
    May 6, 2014
    Messages:
    804
    Aren't the Events.* and SerialEvent stuff relying on the graphical engine?
    I don't think they would trigger for stuff that the player can't see. I could be wrong, though, but that was the understanding I got from my research at the time into the whole "Events vs GameEvents" thing.
     
  20. bane_

    bane_ Howardianism High-Priest

    Joined:
    Nov 27, 2013
    Messages:
    1,559
    These are not mutually exclusive characteristics. They are all tied to the graphical engine, as far as I know, but some do work for stuff the human player can't see. This one is an example!
     

Share This Page