Quick Modding Questions Thread

Im trying (for determining good values) to add the the values into the text shown. Iirc its something like adding a d% or something to the L"" part, and having a ,value but having, as usual, problem with syntax.
Right now it just says "Ranged attack missed", but I'd like to add the numbers to it after like : "Ranged attack missed, airbasecombatstr + getnumUnits - baseCombatstr"

PHP:
	if ((GC.getGameINLINE().getSorenRandNum(100, "Random")) < 50 + airBaseCombatStr() + pPlot->getNumUnits() - pDefender->baseCombatStr())	
	{
		iDamage = 0;
		gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), L"Ranged attack missed", "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
	}

i tried :
(L"Ranged attack missed %d", pPlot->getNumUnits()),
but got a :
1>CvUnit.cpp(12422) : error C2664: 'CvDLLInterfaceIFaceBase::addMessage' : cannot convert parameter 4 from 'int' to 'CvWString'
 
@ DH: in the exe :(
 
I could imagine that the animated LH rendering is part of the engine which they were not allowed to expose. Maybe it was hard to uncouple the rest of the screen from that.
 
vincentz:
Code:
CvWString::format(L"Ranged attack missed %d", pPlot->getNumUnits())
might work, however, normally, this is done through an XML text key. E.g. as in CvUnit::init:
Code:
CvWString szBuffer;
// (...)
// Player name and unit name are parameters
szBuffer = gDLL->getText("TXT_KEY_MISC_SOMEONE_CREATED_UNIT", GET_PLAYER(getOwnerINLINE()).getNameKey(), getNameKey());
// Show szBuffer to player iI
gDLL->getInterfaceIFace()->addMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_WONDER_UNIT_BUILD", MESSAGE_TYPE_MAJOR_EVENT, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"), getX_INLINE(), getY_INLINE(), true, true);
And in Civ4GameTextInfos.xml:
Code:
<TEXT><Tag>TXT_KEY_MISC_SOMEONE_CREATED_UNIT</Tag>
<English>%s1_PlyrName has created %s2_UnitName!</English>
<!-- translations ... -->
</TEXT>
 
Thanks f1rpo. I'll try the casting otherwise I'll go for the text based one :-D

I honestly don't know if it's something I dreamed, but I recall adjusting the size of LH and moving the trade bars, though it could have been in Photoshop and just something i was thinking about doing later :-P
 
Thanks f1rpo. I'll try the casting otherwise I'll go for the text based one :-D

I honestly don't know if it's something I dreamed, but I recall adjusting the size of LH and moving the trade bars, though it could have been in Photoshop and just something i was thinking about doing later :-P

edit : and a spooky doublepost later....
It works :D Its a really nice and easy way to check the calculations and values along the way, and easier than getting into the textfiles first. Thanks :D

gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), CvWString::format(L"Ranged attack missed %d + %d - %d", airBaseCombatStr(), pPlot->getNumUnits(), pDefender->baseCombatStr()), "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
 
Does anyone know where the Diplomacy screen is defined?
@ DH: in the exe :(
This is something, which annoys me quite a lot. It severely limits what you can do to diplomacy. Perhaps the most annoying part is that it isn't bug free (at least in colonization) and being in the exe, bugfixing is not really something we can do. The bug is that under certain conditions, the AI will offer peace, but the request to open the diplomacy window to offer peace vanishes in the exe. Sending the request will make it fetch all sorts of needed data to make the window (leader head and stuff), but then nothing and it just carries on. Setting the two teams to peace and then request the window will make it open, indicating that the bug is a toggled bool check. Why is that check even in the exe?

I was so upset with it at some point that I considered rewriting the diplomacy window from scratch. However I haven't even started doing that and I'm no longer sure that I will. It seems like a big task

So much for being able to fix it then :(. Wonder why they split up the UI elements into some in Python and some in C?
The concept is to set up UI in python. There are some parts in the DLL. They are (mainly?) popup windows with buttons and pedia string generation. My guess is that opening a new window would be ugly in python compared to the relatively clean C++ code. The pedia requires lots of data access, which may or may not be available to python. Also C++ is significantly faster than python, meaning CPU heavy UI elements could make the game lag in python, particularly on minimum system requirements computers.

As for why some screens are in the exe? Who knows? Maybe they have such brilliant code that they wanted to keep it a secret. Or maybe they just didn't consider modder access to screens like that. I think the main issue here is that the exe<->dll interface was not planned as a clean interface from the start. I have encountered a number of features where I think "those doesn't belong in the exe", yet they are still there. For instance GameFont ID setup for yields. It's in the DLL in BTS (good), but in the exe in colonization (quite bad as colonization is the one, which needs this to be modded). The exe sets up all the ids at startup, then check if they are what it set them to be and crashes if they are wrong. After that, the modder can set them to whatever he wants as the exe will no longer need the yield GameFont IDs. It just seems to be a silly limitation, which serves no real purpose.
 
I was so upset with it at some point that I considered rewriting the diplomacy window from scratch. However I haven't even started doing that and I'm no longer sure that I will. It seems like a big task
If possible, that would be great. I definitely also share some of your frustrations with it.
 
I feel like Im taking two steps forward and three steps back with my C++ modding :(
Sorry for ask a lot of stupid questions, but I want a "Return Fire" on my Rangestrike, and need a check to see if pDefender canRangeStrikeAt(plot of original attacker), problem is, how to get the plot of attacker so it fits :
canRangeStrikeAt(const CvPlot* pPlot, int iX, int iY) const

i tried :
if (pDefender->canRangeStrikeAt(this->plot, iX, iY))
but got :
1>CvUnit.cpp(12465) : error C2664: 'CvUnit::canRangeStrikeAt' : cannot convert parameter 1 from 'CvPlot *(void) const' to 'const CvPlot *'

im sure im missing the obvious (as usual), so any help is (as usual) much appreciated :)
 
im sure im missing the obvious (as usual), so any help is (as usual) much appreciated :)
Aiming for something obvious.
Code:
if (pDefender->canRangeStrikeAt(this->plot[COLOR="Red"][B][SIZE="3"]()[/SIZE][/B][/COLOR], iX, iY))
Try that one. Your error message is a bit cryptic though. I suspect there is a nameclash or something, which makes the error handing report less useful than normal.
 
If possible, that would be great. I definitely also share some of your frustrations with it.
That post makes me think. We share a problem and none of us has the solution. However maybe some of us has part of the solution and together we have the complete solution.

There are the following steps:
  1. catch the diplo event before it enters the exe.
  2. open a python window
  3. draw the python window based on diplo event data
  4. python code to get which option the player clicked on and send it to the dll
  5. dll reading the answer and do the requested action (transmit on network if needed)
My abilities for these tasks:
  1. already done it (for a different purpose)
  2. should be doable, though I need research to figure out how
  3. my biggest issue. No idea how to do this. The leaderhead might be the biggest issue.
  4. might be able to figure this one out
  5. fully confident that I can handle this one
My biggest problem is python UI. If I can find somebody to do that, this could very well be done. I have experience in fixing network desyncs and know what it takes to make features work in networked multiplayer. I have made new classes in C++ and then added python interface to them, meaning variable communication between the diplo event and the python window would likely be a new class with a bunch of get/set functions. I have experimented with making C++ code where the code is in new files, meaning adding them to other mods is little more than copying in the cpp/h files.

In short, I have a decent idea on what to do to make a replacement window. I just can't make the actual UI itself. Also my current top priority is M:C. There are some people who are stuck modding until I reach a certain milestone and I don't want to keep them idle for longer than I have to. Any other tasks will have to wait.

Are there any python UI skilled people, who could be interested in a joined effort (presumably next year)? I can easily manage a git server to host the source. It should be a modcomp for BTS, but I assume it shouldn't be too difficult to make something, which works for any civ4, including colonization.
 
2) This is easy. Opening a new screen when a button or command is given can be done via pure python. I done it frequently in my WB, which you can explore for examples. Not at my computer now.

3) Easy as well, perfect sample in pedia.

4) Doable too, although for this case, you should need modnetmessaging to send to all
 
Aiming for something obvious.
Code:
if (pDefender->canRangeStrikeAt(this->plot[COLOR="Red"][B][SIZE="3"]()[/SIZE][/B][/COLOR], iX, iY))
Try that one. Your error message is a bit cryptic though. I suspect there is a nameclash or something, which makes the error handing report less useful than normal.

thanks :goodjob:
I still have an issue though :(
I used this because attacker is not defined and it works, but only the first round. If I end turn and try again it doesnt work (???)
if (pDefender->canRangeStrikeAt(this->plot(), this->getX_INLINE(), this->getY_INLINE()))

Full code :
PHP:
bool CvUnit::rangeStrike(int iX, int iY)
{
	CvUnit* pDefender;
	CvWString szBuffer;
	int iUnitDamage;
	int iDamage;

	CvPlot* pPlot = GC.getMapINLINE().plot(iX, iY);
	if (NULL == pPlot)
	{
		return false;
	}

	if (!canRangeStrikeAt(pPlot, iX, iY))
	{
		return false;
	}

	pDefender = airStrikeTarget(pPlot);

	FAssert(pDefender != NULL);
	FAssert(pDefender->canDefend());

	if (GC.getDefineINT("RANGED_ATTACKS_USE_MOVES") == 0)
	{
		setMadeAttack(true);
	}
//	changeMoves(GC.getMOVE_DENOMINATOR()); Vincentz Rangeattack extra cost
	changeMoves(GC.getMOVE_DENOMINATOR()*5);
	iDamage = rangeCombatDamage(pDefender);
//Vincentz Rangehit check
	if ((GC.getGameINLINE().getSorenRandNum(100, "Random")) > 50 + airBaseCombatStr() + pPlot->getNumUnits() - pDefender->baseCombatStr())	
	{
		iDamage = 0;
		gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), CvWString::format(L"Ranged attack missed %d + %d - %d", airBaseCombatStr(), pPlot->getNumUnits(), pDefender->baseCombatStr()), "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
	}
//Vincentz Rangehit check end	
	iUnitDamage = std::max(pDefender->getDamage(), std::min((pDefender->getDamage() + iDamage), airCombatLimit()));

	szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ARE_ATTACKED_BY_AIR", pDefender->getNameKey(), getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
	//red icon over attacking unit
	gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COMBAT", MESSAGE_TYPE_INFO, getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), this->getX_INLINE(), this->getY_INLINE(), true, true);
	//white icon over defending unit
	gDLL->getInterfaceIFace()->addMessage(pDefender->getOwnerINLINE(), false, 0, L"", "AS2D_COMBAT", MESSAGE_TYPE_DISPLAY_ONLY, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), pDefender->getX_INLINE(), pDefender->getY_INLINE(), true, true);

	szBuffer = gDLL->getText("TXT_KEY_MISC_YOU_ATTACK_BY_AIR", getNameKey(), pDefender->getNameKey(), -(((iUnitDamage - pDefender->getDamage()) * 100) / pDefender->maxHitPoints()));
	gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

//Vincentz Rangehit check
	if (iDamage != 0)
		{
		collateralCombat(pPlot, pDefender);
		}
//Vincentz Rangehit check end	
		
	//set damage but don't update entity damage visibility
	pDefender->setDamage(iUnitDamage, getOwnerINLINE(), false);

	if (pPlot->isActiveVisible(false))
	{
//		gDLL->getInterfaceIFace()->lookAt(plot()->getPoint(), CAMERALOOKAT_NORMAL); //Vincentz lookat
		// Range strike entity mission
		CvMissionDefinition kDefiniton;
		kDefiniton.setMissionTime(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime() * gDLL->getSecsPerTurn());
		kDefiniton.setMissionType(MISSION_RANGE_ATTACK);
		kDefiniton.setPlot(pDefender->plot());
		kDefiniton.setUnit(BATTLE_UNIT_ATTACKER, this);
		kDefiniton.setUnit(BATTLE_UNIT_DEFENDER, pDefender);

		gDLL->getEntityIFace()->AddMission(&kDefiniton);

		//delay death
		pDefender->getGroup()->setMissionTimer(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime());
	}
//Vincentz Strikeback

	if (pDefender->canRangeStrikeAt(this->plot(), this->getX_INLINE(), this->getY_INLINE()))
	{
		gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), true, GC.getEVENT_MESSAGE_TIME(), CvWString::format(L"Can rangestrike back"), "AS2D_COMBAT", MESSAGE_TYPE_INFO, pDefender->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pPlot->getX_INLINE(), pPlot->getY_INLINE());

	iDamage = rangeCombatDamage(this);
	iUnitDamage = std::max(this->getDamage(), std::min((this->getDamage() + iDamage), airCombatLimit()));
	this->setDamage(iUnitDamage, getOwnerINLINE(), false);


	if (pPlot->isActiveVisible(false))
	{
//		gDLL->getInterfaceIFace()->lookAt(plot()->getPoint(), CAMERALOOKAT_NORMAL); //Vincentz lookat
		// Range strike entity mission
		CvMissionDefinition kDefiniton;
		kDefiniton.setMissionTime(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime() * gDLL->getSecsPerTurn());
		kDefiniton.setMissionType(MISSION_RANGE_ATTACK);
		kDefiniton.setPlot(this->plot());
		kDefiniton.setUnit(BATTLE_UNIT_ATTACKER, pDefender);
		kDefiniton.setUnit(BATTLE_UNIT_DEFENDER, this);

		gDLL->getEntityIFace()->AddMission(&kDefiniton);

		//delay death
		this->getGroup()->setMissionTimer(GC.getMissionInfo(MISSION_RANGE_ATTACK).getTime());
	}
	}
	
	return true;
}

edit : I also tried with :
if (pDefender->canRangeStrikeAt(plot(), getX_INLINE(), getY_INLINE()))
if (pDefender->canRangeStrikeAt(plot(), plot()->getX_INLINE(), plot()->getY_INLINE()))
same result. first turn it will, second it wont
 
I'm very interested in this and would like to help where I can. I think my skill set is closer to Nightinggale's (DLL stuff and backend logic), but I'm sure there's something to contribute. I'm less experienced with drawing (good looking) UIs but I'm sure I have something to add there as well.

Maybe there should be some extra brainstorming before we start (I think we're all blocked by other plans for the time being anyway, so let's talk at least). For instance, if we know what information to display in the screen (I'd love optional AI trade values for debug purposes) we can better plan what to expose from the DLL.
 
I made a thread for this. Please continue discussion there so actual questions in this thread are not drowned out.
 
Well, regarding to my Rangestrike, the code is right, however when checking if unit can rangeStrikeAt, it checks whether it can rangestrike, and in there is this little bugger that prevents it for the AI
PHP:
	if (!canMove() && getMoves() > 0)

so... mystery solved.

but only for another to arise...
How to extend or put a pause in between the two strikes (Attack and defend). They occur almost instantly. And I also tried many days to look for a "LookAt if [Watch enemy moves] is ON"
I tried the gDLL->getInterfaceIFace()->lookAt(plot()->getPoint(), CAMERALOOKAT_NORMAL); but is not really efficient as it doesnt look at all the rangestrikes, only 1.
 
Hello, this is an unrelated question, but I think it's in the right place.
Does anyone know if it is possible to use Civ 5 unit or building art in Civ 4? I know that there are tutorials to import civ 4 models into a civ 5 mod, but I am wondering if the inverse is possible.
Thanks
 
Back
Top Bottom