Question from the LUA masters

Mynex

Warlord
Joined
Sep 30, 2010
Messages
287
I have a list of 16k names for US cities (thank you census!).

I know this CAN be done, just not sure if it can be done in Civ.

Create a db; CivName, CityName, Weight
Make a city and a LUA script gets the CivName
Then Randomly selects a name based on the Weight
Then Populates the city name in game.

I'd rather use a db, but if it needs to be an XML, so be it...

I haven't messed around enough with the LUA and what it can do IN civ5 to know if this will work... In theory it should...

I suppose putting it in an XML file would be better for modding purposes, but that's going to be one damned big XML file....

So can I convince one of you Civ5 LUA masters to right the lua for me pretty please? With Cleopatra on top! ;)
 
do you mean you want to populate the table 'Civilization_CityNames' with 16,000 city names, and then when a city is created the lua script would randomly select a name (the random using some 'weight' factor') and set the city name based on that?

there's apparently a SetName() function which i'm guessing it can change the string of a city name, and how the events work, to set the name randomly based on a weight, the name would have to be changed after the city is founded

if all of this is correct, then it shouldn't be that complicated to make a lua script to rename cities, a lua noob could do it as well as a lua master

whats a lua master anyway compared to say a lua noob? the master can do ifs, fors and whiles with his eyes closed and the noob needs reference material? lol
 
do you mean you want to populate the table 'Civilization_CityNames' with 16,000 city names, and then when a city is created the lua script would randomly select a name (the random using some 'weight' factor') and set the city name based on that?

Essentially yes. But have a list of city names for each civ... I've been collecting city name lists from the net and the civ3/4 forums here.

So whatever civs where in game, it would get a name from the db.

there's apparently a SetName() function which i'm guessing it can change the string of a city name, and how the events work, to set the name randomly based on a weight, the name would have to be changed after the city is founded

if all of this is correct, then it shouldn't be that complicated to make a lua script to rename cities, a lua noob could do it as well as a lua master

Currently names are chosen from the xml, in order they appear in that xml. I'm wanting to hijack that process and replace it with the 'go read/random select' from the db (or xml) I create. Renaming is renaming, randomly selecting at founding is what I want to do.

There would need to be some logic checking, simple logic checking in place as well... If the name is already in use, grab another. That simple. :)

whats a lua master anyway compared to say a lua noob? the master can do ifs, fors and whiles with his eyes closed and the noob needs reference material? lol

Well pretty much, but some people have an innate ability with languages, full ones or script... having worked with a lot of coders over the years, and my own attempts at learning.... some people are simply just better at it... their brains seem to be wired to better understand the ins and outs of coding and to (seemingly insanely) do the oddest things with code.

Sadly, I am not one of those people... I have to plod through things, use ref manuals, and beat on other peoples code... and even then I usually don't get the results I want. :(

On the other hand, I've driven coders nuts... I seem to have this uncanny ability to look at code and go "That doesn't look right, you sure that does what it's supposed to?" only to find out it was a bug/error... lol...

Ah well.. one of these days maybe I'll learn 'correctly' to code from the ground up. :p
 
i'm not sure if the process can be hijacked.

maybe between the player, and the found city or B hotkey there is a layer that you can add the checks; would have to look into the UI stuff. but a quick look at the found city functions doesn't seem to have any that would let us pass a string, like settlerunit:foundcity( cityname ). and when it comes to the AI i don't believe there is any such kind of layer to work with

so just going by what i know thats already available, the fastest solution would be to rename cities, and thats if that city rename function even works ( city:SetName() )
 
Well when you select 'edit' on the city name, a new window comes up for you to type the name in...

So maybe the city:SetName() function can be hijacked instead?

I still believe there's got to be a way to hijack the function that grabs the names from the xml listing... may have to wait for the full sdk to be released... might be something inside the dll...
 
if setname does what we think it does, then it's a very simple matter to change a city name the instant it's built. what i'm saying is that having the game decide what name to use for a city to be founded isn't so obvious. there's nothing there that i've seen so far that can let us do that. it's always going to pick the next city name in line in the xml

although (havent tried this yet) if we can update the db with our own values, then its very possible to track a settler, and based on that tracking update the db's list of city names, so when the settler does decide to found a city, it will pull in the desired city name
 
Mynex, you should have a look at the RealNameEarth mod available in the mod browser, I think it rename cities on creation...
 
Hey mummy... Do you think with the SpecificCityInfoDirty function my idea is possible?

That function triggers on city creation, so I'm thinking if this function can be tapped/adapted/hijacked to call a new function;

city:RandomName

This function goes out and reads the db (or xml), grabs the name, checks if the name is already in use, if it is, grabs a different one (repeat check), and when it finally get a name not in use by the civ, then returns it to the UI... or perhaps to city:SetName...
(At some point possibly try a UI with 3 buttons; 'Accept' 'New Name', 'Edit')

The structure of the db;
Civilization Name | City Name | Weight

Simple, direct.

Now the same could be done in xml...

Perhaps a test run using the existing city names and instead of specifying a weight, simply give them all equal weight...?

That's providing we can even a) hijack some function, b) modify said function to do what we want, c) the damn thing even works! :x

anyways... thoughts?
 
yeah but with SerialEventCityCreated which triggers when a city is founded, or if its captured. a quick check to see if its captured can cancel the renaming.

cityinfodirty gets called up often but it can work too provided there's a check to make sure the city isnt being renamed a 2nd or + time
 
yeah but with SerialEventCityCreated which triggers when a city is founded, or if its captured. a quick check to see if its captured can cancel the renaming.

cityinfodirty gets called up often but it can work too provided there's a check to make sure the city isnt being renamed a 2nd or + time

I can see the argument for if a city is captured to not rename it, but historically speaking, that's what happened all the time... so, if it's captured, let it be renamed the random way from the civ doing the capturing list... a later version can give the option to 'keep or rename' if it's too much effort the initial go around.

Avoiding it a '2nd or +' time, yea, that's probably a good idea. ;)
 
this should be a good start. the renaming happens so fast you don't see the original name at all, although there is a notification of the oldname city being founded
Spoiler :

Code:
function cityrenamerandom ( hex, civ, cityid )

	local player = Players[ civ ];
	local city = player:GetCityByID( cityid );

	if ( player:IsMinorCiv() ) then return; end

	local tbl = {};
	local civtype = GameInfo.Civilizations[ player:GetCivilizationType() ].Type; 
	local sqlquery = "select cityname from Civilization_CityNames where civilizationtype = \"" .. civtype .. "\"";

	for name in DB.Query( sqlquery ) do 
		table.insert(tbl, Locale.ConvertTextKey( name.CityName ) ); 
	end 

	local rand = 0;
	local loop = 1;
	while loop == 1 do
		loop = 0;
		rand = math.random(1, #tbl);

		for tmpcity in player:Cities() do
			local name = tmpcity:GetName();
			if ( name == tbl[ rand ] ) then loop = loop + 1; end
		end
	end

	city:SetName( tbl[ rand ] );

end
Events.SerialEventCityCreated.Add ( cityrenamerandom );

and if we're allowed to alter the db, a "used" column could be added to the citynames and then the while loop could be axed out for an extra where clause in the sql
 
Well, We can certainly go that route (altering the DB that is) that would make it easier for people to enter their own civ/city/weight lists as well (using SQL inserts which are not that hard).

But, that 'used' column would need to be set somehow for _only_ the saved games.. which I don't believe we have a way to edit those yet, or do we?

Maybe start with clearing that field when a game starts and then do a search of city names right after adding the 'used' field in there?

As for the notification... *ponders* I'll have to mull that one over... do we know where that particular bit of code is hiding?

I'll put together a quickie DB with the vanilla civs and their city names in it sometime tonight or tomorrow and get it up here...
 
when a game start theres the gameinit event that can go over all the cities and set a used flag to 1, so no saving necessary. if its possible to add a column, and modify the db in game, the default value would be 0, so on new games every city would be set to 0

the notify stuff is somewhere in the vanilla UI files i think
 
when a game start theres the gameinit event that can go over all the cities and set a used flag to 1, so no saving necessary. if its possible to add a column, and modify the db in game, the default value would be 0, so on new games every city would be set to 0

the notify stuff is somewhere in the vanilla UI files i think

Okay, then I'll add a 'Used' column with a default of 0 then.

I'll hunt down the notify stuff... I think I know where it is (been hunting through LUA stuff the last few days. :x)
 
one sqlite db for testing...

All I did was take the xml and convert it over... so the tag names you see in the xml are the tag names in the db. I added the 'Used' column and set it to default 0.

I have a few ideas on tweaking this, but lets see if it works eh? :)
 

Attachments

here's the function you've been looking for:

Players[ 0 ] : AddCityName ( "newcityname" );

this replaces the city names to be used with the ones you add with this function. once it runs out, a city has an empty string as name. that should make everything really simple for you ;)
 
Few possibly interesting functions listed in the civ5lua api html file I found... but no clue what they actually do...

SerialEventCityCreated

InitCity

GetNewCityName - Guessing this one is from the 'edit' option...?

AddCityName

GetNumCityNames

I'll try mucking about with the code you provided above and see what the Players[ 0 ] : AddCityName ( "newcityname" ); ... but my LUA-fu is pretty pathetic... I thought I knew me a wee bit about lua... :blush:
 
Gah! I give up (for now)... I have no idea what to do at this point...

I look at the code you put above and it makes some sense... But damn me if I can figure out where or even how to set this up... and adding in the Players[ 0 ] : AddCityName ( "newcityname" ); is definitely beyond me at this point...

I did some (apparently very) basic lua modding back on NWN... but can't rem a damned bit of it now. :x

*sigh* I don't have the time to refresh/re/learn lua now... so I'm just going to have to shelve this idea until I get more time (ha!). :(
 
Back
Top Bottom