resource from a feature

It would probably be better to do it in the SDK but I'm not the one who would do it.

It's doable in Python, depending on what is your exact request. I don't like too much randomness and I would prefer to base it on some XML tags but I don't know yet if it is possible at all.

I'll come back with a first draft possibly tomorrow.
 
The right way to do this is to add tags to XML and then make the SDK use those tags. It's the cleanest interface and the best performance. However if you really want to avoid the SDK (like if you didn't modify anything else and don't want to compile), then I guess it might be possible to do in python. In that case it's a matter of finding the right function and add code to add a resource if plot.getFeature() == target_feature. That might be possible to add in a way, which is not completely messy.

Regardless of approach, do remember that it would make sense to add to the GUI as well. Getting resources from a plot without the GUI telling that the plot is producing that resource is less than ideal.

Maybe the easiest solution is to add code to add a bonus on the feature and remove the bonus if the feature is removed. AI and GUI code is already present to handle bonus resources just fine this way. It would require hooking into setFeature to assign the bonus resource for the plot, which I think is doable from python. The only sideeffect that I can think of is the max one bonus for each plot, meaning you can't have say a game bonus and a bonus from the feature.
 
Here is my Python approach. There is no problem with the GUI, I have even added a message informing of the result. As I said, SDK is the best solution but I can't provide it. Since Nightinggale didn't either, here is my Python code. :p

To complement this, you should inform us what are exactly your expectations. Also, how many couples Feature => Bonus do you think you need?

Some explanations:

In CvEventManager.py, look for "FeatureBonusSpawn".

Right now, randomly, it adds a Banana Bonus to a Jungle Feature.

In the __init__ function, you will find this:
self.iAppearanceBanana = 15
It means 15% of chance of spawning when conditions are met (see below).

In the onBeginGameTurn function, you will find this:
Code:
if (iGameTurn >= ( self.MaxTurns[0] / 4 )) and not (iGameTurn >= self.MaxTurns[0]) and (iGameTurn % (self.MaxTurns[0] / 100) == 0):

Custom:
1) starts to function after game is 1/4 started
2) just to say stop to the code if game time (turns) is over
3) every 1/100 of total game turns, function starts (I love to play 6000 turns, so it would fire every 60 turns).

Then:
Code:
if CyGame().getSorenRandNum(100,"BonusSpawn") <= self.iAppearanceBanana:
you have 15% of chance to have a new banana in a jungle.

Then:
if yes to all, select a jungle (without a bonus) randomly and adds the banana. If you own the plot and are human (not :borg:), you get a message.

Keep me posted and have fun! :)
 

Attachments

That's totally not what I had in mind, though it's not bad. I would scale the percentage to map size, allowing more bonuses to bigger maps and possibly reduce the chance based on the number of existing bonuses to prevent overflowing the map. Those are balance issues and not really issues with the core design of this concept.

However now the real question is: what is the question? It doesn't look like we read the same problem in the question, which mean keldath needs to be a more specific if this doesn't meets the requirements.
 
huh. wow very nice!

its so great of you to help out with this, really, modderes helping modders, thats always touches me :)
thank you so much.

ill test it in a day.

basically, my goal is to set a specific feature, that for every plot that has these feature there would be that bonus, until the feature is no more.

so if i want the function to work from turn 1, i need to - ( self.MaxTurns[0] / 1)) ?

and for 100% - self.iAppearanceBanana = 100?

also - self.iAppearanceBanana can be changed to - self.iAppearanceBlablabla? (on all the refering code?

also - if i wish to define another feature with another bonus - i should duplicate the rows? or the code it self?


again! many many thanks!


edit:
Nightinggale - yes you raise some balance issues, though, it is not the case, in my purpose, the goal is simple
feature x contains bonus y.
the controls for the feature - are done by iappearance, idisappearance , igrowth in the xml
the placement - can be defined with the mapgenerator.py.
thats it i guess, simple and clean.
 
No problem, I made it so that anyone can use it and adapt it to their need.

In your case, it's much more simple, just add this in CvEventManager:
Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]
		CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
		
		# isenchine for keldath: FeatureBonusSpawn Start
		iFeature = gc.getInfoTypeForString("FEATURE_JUNGLE")
		iBonus = gc.getInfoTypeForString("BONUS_BANANA")
		for iPlotLoop in xrange(CyMap().numPlots()):
			pPlot = CyMap().plotByIndex(iPlotLoop)
			if (pPlot.getFeatureType() == iFeature) and (pPlot.getBonusType(-1) == -1):
				pPlot.setBonusType(iBonus)
		# isenchine for keldath: FeatureBonusSpawn End

Forget all the rest, including the Text file. Repeat the whole section as many times as you want. The problem here is that it will run this code every turn, even when it is not needed.
 
In your case, it's much more simple, just add this in CvEventManager:
Code:
	def onBeginGameTurn(self, argsList):
		'Called at the beginning of the end of each turn'
		iGameTurn = argsList[0]
		CvTopCivs.CvTopCivs().turnChecker(iGameTurn)
		
		# isenchine for keldath: FeatureBonusSpawn Start
		iFeature = gc.getInfoTypeForString("FEATURE_JUNGLE")
		iBonus = gc.getInfoTypeForString("BONUS_BANANA")
		for iPlotLoop in xrange(CyMap().numPlots()):
			pPlot = CyMap().plotByIndex(iPlotLoop)
			if (pPlot.getFeatureType() == iFeature) and (pPlot.getBonusType(-1) == -1):
				pPlot.setBonusType(iBonus)
			[B]elif (pPlot.getFeatureType() != iFeature) and (pPlot.getBonusType(-1) == iBonus):
				pPlot.setBonusType(iBonus)[/B]
		# isenchine for keldath: FeatureBonusSpawn End
I added bold text to remove the bonus if the feature is gone. It's not ideal and bonus add/remove will not take place until the next turn if a feature is added/removed, but it should get the job done.

The correct approach would be to modify CvPlot::setFeatureType(). Since it appears to lack python callback code, it would have to be done in the DLL. Doing it here would allow setting the bonus instantly instead of waiting for the next turn to start. Maybe the best would be to add this function

PHP:
void CvPlot::setFeatureBonus()
{
	if (getFeatureType() == FEATURE_DUMMY && getBonusType() == NO_BONUS)
	{
		setBonus(BONUS_DUNNY);
	}
	else if (getFeatureType() != FEATURE_DUMMY && getBonusType() == BONUS_DUNNY)
	{
		setBonusType(NO_BONUS);
	}
}
This function is then called as the last thing to do in CvPlot::setFeatureType(). It might also have to be called at other times, like on game start (not turn, game) in case the map generator fails to add the needed bonuses. I'm not 100% sure if the map generator will honour setFeatureType() setup like this. If it's not required to be called elsewhere, you might as well add the if-else-if setup directly in CvPlot::setFeatureType().

Needless to say, the DLL solution is way faster because not only is C++ way faster, it is also only called when there is a change and not every turn regardless of the need to change anything.
 
ohh nice, great changes.

i will use those. thanks.

Nightinggale-
the dll code that you wrote?

this code - does the same thing? in the _dummy - i state the feature or bonus i desire and thats it?
just use this part of code? will it also remove the bonus after? and wher in the plot.cpp should i set it?
 
Nightinggale-
the dll code that you wrote?

this code - does the same thing? in the _dummy - i state the feature or bonus i desire and thats it?
just use this part of code? will it also remove the bonus after? and wher in the plot.cpp should i set it?
Err... somehow failure to tell python from C++ worries me if you intend to modify the DLL. But yeah, it's C++ code for the DLL and it should add and remove when the feature on the plot updates.

I wrote dummy feature and bonus. Naturally it should be replaced with whatever feature and bonus you have in mind as there is no dummy, at least not in vanilla. The reason why I picked dummy is... well I had to call it something and you didn't tell which feature/bonus you intend to use and I just wrote whatever came to my mind.

Actually it just occurred to me that I screwed up regarding the dummy part. I somehow assumed the indexes to be hardcoded in the DLL, but actually they aren't. Instead they should be looked up based on the string using GC.getDefineINT(), in which case it should be
PHP:
if (getFeatureType() == GC.getDefineINT("FEATURE_DUMMY") && getBonusType() == NO_BONUS)
This will look up the index from XML and do what it is intended to do. I mainly mod colonization and that one has more hardcoded values than BTS. Hardcoding is easier to code and executes faster, but it opens up for creating new types of bugs if you mod XML only.

NO_BONUS and NO_FEATURE are hardcoded though and are safe to use. All NO_* hardcoding are set to -1 in CvEnums.h.
 
ok,
cool, i got you on the dummy issue.
thanks.

ok, so ill try both codes, the dll, and the python, ill see who serves me better :)

many many thanks friends,
if you got any more ideas how to improves this that would be cool.
another option i thought, is to add a freebonus tag for the features them selfs but i guess thats more complicated code , and besides if what you guys provided me works, it will be enough :().

edit:

oh also if you fixed the feature to gc.getdfineint,

then :

setBonus(BONUS_DUNNY) should be setBonus("BONUS_DUNNY")?

and - no need for something like - gc.getdfineint for the bonues?
 
There is a python function onPlotFeatureRemoved which you can use instead of Nightingale's suggested code changes in bold. It will not make any difference to game speed but it would happen when the feature is lost. Something like:-

Code:
 def onPlotFeatureRemoved(self, argsList):
    'Plot Revealed'
    pPlot = argsList[0]
    iFeatureType = argsList[1]
    pCity = argsList[2] # This can be null

    iFeature = gc.getInfoTypeForString("FEATURE_JUNGLE")
    iBonus = gc.getInfoTypeForString("BONUS_BANANA")
    if (pPlot.getFeatureType() == iFeature) and (pPlot.getBonusType(-1) == iBonus):
        pPlot.setBonusType([B]-1[/B])

Note. is suggested changes were not right as it would add the bonus again not remove it. I think:confused:
 
oh also if you fixed the feature to gc.getdfineint,

then :

setBonus(BONUS_DUNNY) should be setBonus("BONUS_DUNNY")?

and - no need for something like - gc.getdfineint for the bonues?
Yeah, it's the same. I see the python code is using gc.getInfoTypeForString("FEATURE_JUNGLE"). The DLL code can use GC.getInfoTypeForString("FEATURE_JUNGLE"). I'm not 100% sure when each one is correct to use, but my experience tells me that they are often interchangable. Perhaps it would be most correct to only use getInfoTypeForString for this usage.

This mean the correct bonus would be
PHP:
setBonus(GC.getInfoTypeForString("FEATURE_DUMMY"))
You might need to typecast as well.

getInfoTypeForString and getDefineINT are both somewhat slow functions btw, which is why I usually cache the result. In the most simple way, a cache would be like this:
PHP:
// cache variables
static FeatureTypes eFeature = (FeatureTypes)GC.getInfoTypeForString("FEATURE_DUMMY");
static BonusTypes eBonus = (BonusTypes)GC.getInfoTypeForString("BONUS_DUMMY");

if (getFeatureType() == eFeature && getBonusType() == NO_BONUS) 
{ 
    setBonus(eBonus); 
} 
else if (getFeatureType() != eFeature && getBonusType() == eBonus) 
{ 
    setBonusType(NO_BONUS); 
}
static mean the line will only execute the first time the line is reached. The variable is then saved in memory and the next time the function is called, the save variable (hence value) will be used without looking it up using one of the slow functions. It's not the most efficient way to cache commonly used variables, but good enough for a simple case like this one. Do note that it only works because it caches XML data, which never changes while the game is running.

Python can't use static variables, meaning this approach is a DLL only solution.

While it isn't critical and the code would work without it, I have seen too many slow implementations to not mention when I see an easy to implement improvement. It matters more than most people realize.
 
There is a python function onPlotFeatureRemoved which you can use instead of Nightingale's suggested code changes in bold. It will not make any difference to game speed but it would happen when the feature is lost. Something like:-

Code:
 def onPlotFeatureRemoved(self, argsList):
    'Plot Revealed'
    pPlot = argsList[0]
    iFeatureType = argsList[1]
    pCity = argsList[2] # This can be null

    iFeature = gc.getInfoTypeForString("FEATURE_JUNGLE")
    iBonus = gc.getInfoTypeForString("BONUS_BANANA")
    if (pPlot.getFeatureType() == iFeature) and (pPlot.getBonusType(-1) == iBonus):
        pPlot.setBonusType([B]-1[/B])

Note. is suggested changes were not right as it would add the bonus again not remove it. I think:confused:

Code:
iFeatureType = argsList[2]
pCity = argsList[1]
is the correct one. BTS named the variables wrongly, which is extremely misleading.

P.S.
Both the dll and python methods will lead to side effects.
Informing the player which jungle has an unrevealed resource, since that jungle will not have the usual resource and is barren.
 
Both the dll and python methods will lead to side effects.
Informing the player which jungle has an unrevealed resource, since that jungle will not have the usual resource and is barren.
I was thinking of the issue of existing bonuses, but didn't think of hidden bonuses. None of the proposed solutions are any good :(

The only thing I can think of to solve this is back to my original proposed solution, which I didn't code due to complexity. Edit CvPlot::updatePlotGroupBonus() to add a resource if the plot has a certain feature. That should provide one resource for each feature to the trade network.

However doing that opens for other problems. The GUI for the plot will not tell about the resource, though the city screen should display it. The AI would ignore it too, meaning it will add the need for new AI code to want to add this feature to the trade network. Done right, it should be aware of the resource and predict that it will gain it. However a little cheat is to tell it to just add the chosen feature to the trade network without doing anything for explaining why. The end result is likely more or less the same and it would be easier to code (I think).

If this is coded, then the plot can provide resources from both a bonus and a feature independently from each other.

Coding this is an issue though. I already spent more time on this than I originally planned and coding what I propose now is not a 5 minute job. Part of the issue is that I have absolutely no use for this feature myself. If I could think of a reason to code it, then it would be a different matter.... Actually I might have an idea where I might be able to use it. I will get back to you on that one.
 
Hey guys, i see youve been busy,

Im at wirk so ill refer briefly.

As for informing a player, and hidden bonus,
Since ill set thr tech reveal in the feature and the bonus to the same tech, along with trade tech, there wont be an issue with hidden ones.

Ai, ai should refer to the plot normal, aling with the improvement it will be build upon.

Basically, if this getting complicated. The no need,
Just make the feature dissapear right after bonus was created,
Ican combine platyings depletion mod to removevthe bonus upon usege.

So i guess that would be the easiest way, just make that appearnce of a feature, on game generation and growth on a plot transforms intona bonus, that will be perfect also.


What do you think?

One more thing, no need to inform a player on bonus popup, the feature growth allready does it.
And upon map generation, or first turn, all the features are transfirned to the bonus so the ai and player seas it as a regular bonus.
 
As for informing a player, and hidden bonus,
Since ill set thr tech reveal in the feature and the bonus to the same tech, along with trade tech, there wont be an issue with hidden ones.
The problem is that say we add BONUS_FEATURE to all the plots with the feature in question and then if there is BONUS_URANIUM on the plot. You can use the feature bonus, but not uranium, meaning if a plot with the feature produces no resources, you know it has an undiscovered bonus, in this example uranium, though it could be any undiscovered bonus. This is unavoidable if the code design is based on adding the bonus. Well, alternatively it can overwrite the bonuses on the plots, in which case the uranium would be lost. I'm not sure that would be ideal either.

I looked a bit into "the real solution" and I don't think the benefit is worth the time for this feature. The more I think about it, the more potential issues it contains and would need checking and possibly coding. This makes the time spend too great compared to the gain, which mean I better invest the time is more important issues/bugfixes.

Another thing. It just occurred to me that I said something about investigating some Barsoom issue a long while ago and I never got around to actually do it. Something about the game hanging or something, but now I don't remember. Is there still a hanging issue?
 
Hey guys, i see youve been busy,

Im at wirk so ill refer briefly.

As for informing a player, and hidden bonus,
Since ill set thr tech reveal in the feature and the bonus to the same tech, along with trade tech, there wont be an issue with hidden ones.

Ai, ai should refer to the plot normal, aling with the improvement it will be build upon.

Basically, if this getting complicated. The no need,
Just make the feature dissapear right after bonus was created,
Ican combine platyings depletion mod to removevthe bonus upon usege.

So i guess that would be the easiest way, just make that appearnce of a feature, on game generation and growth on a plot transforms intona bonus, that will be perfect also.


What do you think?

One more thing, no need to inform a player on bonus popup, the feature growth allready does it.
And upon map generation, or first turn, all the features are transfirned to the bonus so the ai and player seas it as a regular bonus.

If your intention is that on game start, all Feature X will be converted into Bonus Y, while Feature X no longer exist in the game since they are removed upon creation of Bonus Y...

Then in the first place why bother having Feature X, just let Bonus Y spawn naturally upon map generation...
 
V I see nightingale, time is precious,
I understand the problem, i guesd i can use the code you brought me here, and make sure no other resource can appesr on that speciphic feature(in the bonus tag, tgere has to be a defenician if you eant a bonus yo appear on a feature).
So i guess that will benough, just to make sure only that tupe of bonus on that feature.

Could you tell me above all the top codes which is the best to pick?

Sweet of you to remember barsoom:) all good there fot the time being. Im developing a new mod:).


Platy, for you quastion, cause i need something to combine eith your depleted resources mod, since i will have a depelion of resources when worked, i wish new ones to pop out, and not by discover rand on the improvement tag. Cheers.
 
Back
Top Bottom