{
GET(TechnoClass*, pKiller, EDI);
GET(TechnoClass*, pVictim, ESI);
GET(int, VictimCost, EBP);
TechnoClass* pExperience = NULL;
float ExpFactor = 1.0F;
if(pKiller->Airstrike) {
if(TechnoClass* pDesignator = pKiller->Airstrike->Owner) {
if(TechnoTypeExt::ExtData *pTDesignatorData = TechnoTypeExt::ExtMap.Find(pDesignator->GetTechnoType())) {
if(pTDesignatorData->ExperienceFromAirstrike) {
pKiller = pDesignator;
ExpFactor *= pTDesignatorData->AirstrikeExperienceModifier;
}
}
}
}
TechnoTypeClass* pTKiller = pKiller->GetTechnoType();
TechnoClass* pTransporter = pKiller->Transporter;
TechnoTypeExt::ExtData *pTKillerData = TechnoTypeExt::ExtMap.Find(pTKiller);
TechnoTypeExt::ExtData *pTTransporterData = NULL;
bool TransporterAndKillerAllied = true;
bool promoteImmediately = false;
if(pTransporter) {
pTTransporterData = TechnoTypeExt::ExtMap.Find(pTransporter->GetTechnoType());
TransporterAndKillerAllied = pTransporter->Owner->IsAlliedWith(pKiller);
}
if(pKiller->InOpenToppedTransport && pTransporter) {
TechnoTypeClass* pTTransporter = pTransporter->GetTechnoType();
if((!pTTransporter->Trainable || pTTransporterData->PassengersGainExperience) && (pTransporter->Veterancy.IsElite() || !TransporterAndKillerAllied) && pTKiller->Trainable) {
pExperience = pKiller;
ExpFactor *= pTTransporterData->PassengerExperienceModifier;
} else if(pTTransporter->Trainable && pTTransporterData->ExperienceFromPassengers && TransporterAndKillerAllied) {
pExperience = pTransporter;
}
} else if(pTKiller->Gunner) {
FootClass* pGunner = pKiller->Passengers.GetFirstPassenger();
if(pTKiller->Trainable && !pKiller->Veterancy.IsElite() && (!pGunner || pTKillerData->ExperienceFromPassengers)) {
pExperience = pKiller;
} else if(pGunner && (pKiller->Veterancy.IsElite() || !pTKillerData->ExperienceFromPassengers) && pGunner->GetTechnoType()->Trainable && pTKillerData->PassengersGainExperience) {
pExperience = pGunner;
ExpFactor *= pTKillerData->PassengerExperienceModifier;
promoteImmediately = true;
}
} else if(pTKiller->Trainable) {
pExperience = pKiller;
} else if(pTKiller->MissileSpawn) {
if(TechnoClass* pSpawner = pKiller->SpawnOwner) {
TechnoTypeClass* pTSpawner = pSpawner->GetTechnoType();
if(pTSpawner->Trainable) {
pExperience = pSpawner;
}
}
} else if(pKiller->CanOccupyFire()) {
if(BuildingClass* pKillerBld = specific_cast<BuildingClass *>(pKiller)) {
InfantryClass* pOccupant = pKillerBld->Occupants[pKillerBld->FiringOccupantIndex];
pExperience = pOccupant;
}
}
if(pExperience) {
int KillerCost = pExperience->GetTechnoType()->GetActualCost(pExperience->Owner);
int WeightedVictimCost = (int)(VictimCost * ExpFactor);
if(pExperience->Owner->IsAlliedWith(pKiller)) {
if(pExperience->MindControlledBy && !pExperience->MindControlledBy->Owner->IsAlliedWith(pVictim->Owner)) {
TechnoTypeClass* pTController = pExperience->MindControlledBy->GetTechnoType();
if(TechnoTypeExt::ExtData* pTControllerData = TechnoTypeExt::ExtMap.Find(pTController)) {
WeightedVictimCost = (int)(WeightedVictimCost * pTControllerData->MindControlExperienceVictimModifier);
if(pTController->Trainable) {
int MindControllerCost = pTController->GetActualCost(pExperience->MindControlledByHouse);
pExperience->MindControlledBy->Veterancy.Add(MindControllerCost, (int)(WeightedVictimCost * pTControllerData->MindControlExperienceSelfModifier));
}
}
}
pExperience->Veterancy.Add(KillerCost, WeightedVictimCost);
if(promoteImmediately) {
eRank newRank = pExperience->Veterancy.GetRemainingLevel();
if(pExperience->CurrentRanking != newRank) {
if(pExperience->CurrentRanking != -1) {
int sound = -1;
if(pExperience->Veterancy.IsVeteran()) {
sound = RulesClass::Instance->UpgradeVeteranSound;
} else if (pExperience->Veterancy.IsElite()) {
sound = RulesClass::Instance->UpgradeEliteSound;
}
if(sound != -1 && pExperience->Owner->IsHumanoid()) {
VocClass::PlayAt(sound, &pExperience->Transporter->Location, NULL);
VoxClass::Play("EVA_UnitPromoted");
}
}
pExperience->CurrentRanking = newRank;
}
}
}
}
return 0x702FF5;
}