CorniI
Guest
Hi,
nachdem Desti ja das Targetin-Verhalten vor ein paar Monaten austesten wollte, aber nicht wirklich erfolgreich war, hier der Code, der das für Diablo macht. Jeder Spieler bekommt einen "Rank" zugewiesen, und die Unit, mit dem höchsten Rank ist dann das Ziel der nächsten Attacke, das Verhalten hat desti ja beschrieben.
Bei 1 oder 2 Sachen bin ich mir noch nihct ganz sicher, v.a. weil ich sie nicht reproduzieren konnte, aber das müsste so stimmen
Der Code ist in C(++) geschrieben, bei Fragen, einfach posten, ich gehe jedoch von grundlegenden Kenntnissen einer Programmiersprache aus
Und hier die (noch unvollständig in den Code-Pfaden für Hirelings+Barb-Allys in a5, und deshalb noch nicht geteste) Funktion, die dann die Unit wirklich auswählt:
ACHTUNG: Obwohl Baal ähnlichen Code verwenden kann, DIESER ist es NICHT, außer Blizz hat c&p benutzt (gut möglich )
MfG
Corni
EDIT: Da der Code bei mir ziemlich beschissen umbricht (1400x900, 16:10 Display), empfehle ich, den Code in Wordpad oder so zu kopieren...
nachdem Desti ja das Targetin-Verhalten vor ein paar Monaten austesten wollte, aber nicht wirklich erfolgreich war, hier der Code, der das für Diablo macht. Jeder Spieler bekommt einen "Rank" zugewiesen, und die Unit, mit dem höchsten Rank ist dann das Ziel der nächsten Attacke, das Verhalten hat desti ja beschrieben.
Bei 1 oder 2 Sachen bin ich mir noch nihct ganz sicher, v.a. weil ich sie nicht reproduzieren konnte, aber das müsste so stimmen
Der Code ist in C(++) geschrieben, bei Fragen, einfach posten, ich gehe jedoch von grundlegenden Kenntnissen einer Programmiersprache aus
Code:
DWORD __fastcall rankTarget(BlizzGame* ptGame, BlizzUnit* ptMonster, BlizzUnit* ptUnit, diabloAiStruct* ptStrc)
{
ASSERT(ptGame!=NULL);
ASSERT(ptMonster!=NULL);
BOOL inMeeleRange=isInRange(ptMonster,ptUnit,0);
DWORD tooFar=0;
if(inMeeleRange)
inMeeleRange=100;
//unsure why the unit should get an bonus for that...
if(ptStrc!=NULL&&getAnotherIsometricDistance(ptMonster,ptStrc->xPos,ptStrc->yPos)>85&&getAnotherIsometricDistance(ptUnit,ptStrc->xPos,ptStrc->yPos)>85)
{
//var=100
tooFar=100;
}
//resistances
DWORD damageresist=getStatSigned(ptUnit,STAT_DAMAGERESIST,0);
DWORD fireresist=getStatSigned(ptUnit,STAT_FIRERESIST,0);
DWORD lightresist=getStatSigned(ptUnit,STAT_LIGHTRESIST,0);
DWORD magicresist=getStatSigned(ptUnit,STAT_MAGICRESIST,0);
DWORD coldresist=0;
if(inMeeleRange)
DWORD coldresist=getStatSigned(ptUnit,STAT_COLDRESIST,0);
DWORD resisttotal=4*damageresist+8*magicresist+coldresist+fireresist+lightresist;
resisttotal/=15;
//damage
DWORD maxdamage=getStatSigned(ptUnit,STAT_MAXDAMAGE,0);
DWORD lightmaxdam=getStatSigned(ptUnit,STAT_LIGHTMAXDAM,0);
DWORD firemaxdam=getStatSigned(ptUnit,STAT_FIREMAXDAM,0);
DWORD coldmaxdam=getStatSigned(ptUnit,STAT_COLDMAXDAM,0);
DWORD poisonmaxdam=getStatSigned(ptUnit,STAT_POISONMAXDAM,0);
DWORD magicmaxdam=getStatSigned(ptUnit,STAT_MAGICMAXDAM,0);
poisonmaxdam/=64;
DWORD damtotal=maxdamage+poisonmaxdam+lightmaxdam+firemaxdam+magicmaxdam;
damtotal=abs(damtotal)/2;
//stae cold present?
DWORD stateCold=0;
if(checkState(ptUnit,STATE_COLD))
stateCold=100;
//Life
int life=getLifePct(ptUnit);
if(life>=20)
life=0;
else
life=100;
//Skills+attackRank
DWORD skillLevelLeft=0,skillIdLeft=0,skillLevelRight=0,skillIdRight=0;
char attackRankRight=0,attackRankLeft=0;
BlizzSkill* ptSkillLeft=getSkillLeft(ptUnit);
BlizzSkill* ptSkillRight=getSkillRight(ptUnit);
if(ptSkillLeft)
{
skillLevelLeft=getCurrentSkillLevel(ptUnit,ptSkillLeft,1);
skillIdLeft=getSkillId(ptSkillLeft,__FILE__,__LINE__);
if(skillIdLeft<0||(*sgptDataTables)->nSkills<skillIdLeft)
NEFEXUTIL_Error("Nonmatching skill here, exiting",__FILE__,__LINE__,1);
attackRankLeft=(*sgptDataTables)->ptSkillsTxt->attackrank;
}
if(ptSkillRight)
{
skillLevelRight=getCurrentSkillLevel(ptUnit,ptSkillRight,1);
skillIdRight=getSkillId(ptSkillLeft,__FILE__,__LINE__);
if(skillIdRight<0||(*sgptDataTables)->nSkills<skillIdRight)
NEFEXUTIL_Error("Nonmatching skill here, exiting",__FILE__,__LINE__,1);
attackRankRight=(*sgptDataTables)->ptSkillsTxt->attackrank;
}
int threatSkills=attackRankRight*skillLevelRight+attackRankLeft*skillLevelLeft;
threatSkills&=3;//Limit it to 3 as max
threatSkills=abs(threatSkills);//is this just a compiler safety or really needed?
threatSkills/=4; //weird...
if(ptUnit->typeNo==UNIT_MONSTER)
{
FileMonstatsTable* ptMonstats=NULL;
if((*sgptDataTables)->nMonster<ptUnit->classNo)
return 0;
ptMonstats=(*sgptDataTables)->ptMonstats;
ptMonstats+=ptUnit->classNo;
if(ptMonstats->threat<=1)
return 0;
}
//compute the rank
/*6FCE866F |> 8B4424 1C MOV EAX,DWORD PTR SS:[ESP+1C] ; EAX=TooFar????
6FCE8673 |. 8B4C24 30 MOV ECX,DWORD PTR SS:[ESP+30] ; inmeelerangebonus?
6FCE8677 |. 03C1 ADD EAX,ECX ; EAX=^^^^
6FCE8679 |. 8B4C24 24 MOV ECX,DWORD PTR SS:[ESP+24] ; ECX=I guess resistrank
6FCE867D |. 8D547D 00 LEA EDX,DWORD PTR SS:[EBP+EDI*2] ; EDX=threatSkills+2*statecoldset
6FCE8681 |. 8D0C81 LEA ECX,DWORD PTR DS:[ECX+EAX*4] ; ECX=resistRank+4*tooFar+inmeelerangebonus
6FCE8684 |. 03D3 ADD EDX,EBX ; threatSkill+2*statecold+damagerank
6FCE8686 |. 03C1 ADD EAX,ECX ; EAX=ECX+EAX
6FCE8688 |. 8B4C24 28 MOV ECX,DWORD PTR SS:[ESP+28] ; ECX=lifeBonus??
6FCE868C |. 8D0C49 LEA ECX,DWORD PTR DS:[ECX+ECX*2] ; lifeBonus*3
6FCE868F |. 8D1450 LEA EDX,DWORD PTR DS:[EAX+EDX*2]
6FCE8692 |. 03CA ADD ECX,EDX
*/
/*DWORD eax=tooFar+retByPath;
DWORD edx=threatSkills+(2*stateCold);
DWORD ecx=resisttotal+(4*eax);
edx=edx+damtotal;
eax=eax+ecx;
ecx=3*life;
edx=eax+2*edx;
ecx=ecx+edx;*/
//and now the real :D
//DWORD eax=tooFar+retByPath;
//DWORD edx=threatSkills+(2*stateCold);
//DWORD ecx=resisttotal+(4*tooFar+retByPath);
//edx=threatSkills+(2*stateCold)+damtotal;
//eax=tooFar+retByPath+resisttotal+(4*tooFar+retByPath);
//ecx=3*life;
//edx=tooFar+retByPath+resisttotal+(4*tooFar+retByPath)+2*(threatSkills+(2*stateCold)+damtotal);
//DWORD totalRank=(3*life)+tooFar+retByPath+resisttotal+(4*tooFar)+retByPath+2*(threatSkills+(2*stateCold)+damtotal);
DWORD totalRank=tooFar + inMeeleRange + resisttotal + 4*tooFar + 4*inMeeleRange + 2*threatSkills + 4*stateCold + 2*damtotal + 3*life;
totalRank/=22;
if(!totalRank)
return 1;
return totalRank;
}
Code:
BlizzUnit* __fastcall getTargetDiablo(BlizzGame* ptGame, BlizzUnit* ptMonster, DWORD* highestRankFound, DWORD* noUnitsChecked, diabloAiStruct* ptStrc, pfnFindTargetFunc* pfnFindTarget)
{
ASSERT(pfnFindTarget!=NULL);
BlizzUnitNode* ptTargetNode=ptGame->ptUnitNodes[0];
BlizzUnitNode** pptTargetNode=ptGame->ptUnitNodes;
DWORD i=0,targetRank=0,highestRank=0,unitsChecked=0;
BlizzUnit* ptTarget=NULL;
BlizzUnit* highestRankedUnit=NULL;
WORD xPos,yPos;
getCoords(ptMonster,xPos,yPos);
while(i<8)
{
ptTargetNode=*pptTargetNode;
if(ptTargetNode!=NULL)
{
ptTarget=ptTargetNode->ptUnit;
//come up with own assertation set
ASSERT(ptTarget!=NULL);
ASSERT(ptTarget->typeNo==UNIT_PLAYER)
if((*pfnFindTarget)(ptMonster,ptTarget)==true)
{
if(ptTarget->modeNo!=PLRMODE_DEATH&&ptTarget->modeNo!=PLRMODE_DEAD)
targetRank=rankTarget(ptGame,ptMonster,ptTarget,ptStrc);
else
targetRank=0;
while(1)
{
if(highestRank<targetRank)
{
highestRank=targetRank;
highestRankedUnit=ptTarget;
}
ptTargetNode=ptTargetNode->ptNext;
unitsChecked++;
if(ptTargetNode==NULL)
break;
ptTarget=ptTargetNode->ptUnit;
targetRank=rankTarget(ptGame,ptMonster,ptTarget,ptStrc);
}
}
}
pptTargetNode++;
ptTargetNode=*pptTargetNode;
i++;
}
//now we have a good ranked Target in ptTarget
if(ptTargetNode!=NULL)
{
//later, dunno exactly what it is
}
if(ptGame->ptUnitNodes[9]!=NULL)
{
//other stuff for barbs in a5, later
}
*noUnitsChecked=unitsChecked;
*highestRankFound=highestRank;
return highestRankedUnit;
}
MfG
Corni
EDIT: Da der Code bei mir ziemlich beschissen umbricht (1400x900, 16:10 Display), empfehle ich, den Code in Wordpad oder so zu kopieren...