⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 economytracker.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

		if (!found) {
			return;
		}
	}

	assert(builderList != NULL);

	float metalUsage = 0;
	float energyUsage = 0;
	float maxBuildPower = 0;
	float maxAssignedBuildPower = 0;

	for (list<int>::iterator i = builderList->begin(); i != builderList->end(); i++) {
		int builder = *i;
		UnitResourceInfo resourceInfo;
		bool isAlive = ai->cb->GetUnitResourceInfo(builder, &resourceInfo);
		// TODO: uncomment this
		// assert(isAlive);
		if (!isAlive)
			continue;

		metalUsage += resourceInfo.metalUse;
		energyUsage += resourceInfo.energyUse;
		maxAssignedBuildPower += ai->cb->GetUnitDef(builder)->buildSpeed;
		const UnitDef * unitDefBuilder = ai->cb->GetUnitDef(builder);

		if (resourceInfo.metalUse > unitDefBuilder->metalUpkeep) {
			// is this needed?
			maxBuildPower += ai->cb->GetUnitDef(builder)->buildSpeed;
		}
	}

	if (!bt->buildTask) {
		assert(ai->cb->GetUnitDef(bt->factory) != NULL); // This will fail
		maxAssignedBuildPower += ai->cb->GetUnitDef(bt->factory)->buildSpeed;
		maxBuildPower += ai->cb->GetUnitDef(bt->factory)->buildSpeed;
	}

	bt->assignedTotalBuildPower = maxAssignedBuildPower;
	bt->maxTotalBuildPower = maxBuildPower;
	// remove the factory from factory->supportbuilders (if it was added)

	// find how much of the unitUnderConstruction is done
	float hp = ai->cb->GetUnitHealth(unitUnderConstruction);
	float oldHP = bt->hpLastFrame;
	float endHp = unitDef->health;
	float eNeed = unitDef->energyCost;
	float mNeed = unitDef->metalCost;
	float buildTime = unitDef->buildTime;
	// NOTE: the damage part needs testing
	float builtRatio = (hp + bt->damage) / endHp;
//	float usedE = builtRatio * eNeed;
//	float usedM = builtRatio * mNeed;
//	float currentBuildPower = energyUsage / currentMaxE_usage;
//	float currentBuildPower2 = metalUsage / currentMaxM_usage
//
//	if(currentBuildPower == 0)
//		currentBuildPower = 0.00000000000000001;
//
//	float eta = (((1.0 - builtRatio) * buildTime) / maxBuildPower ) / currentBuildPower;

	// builders and factories are different (factories
	// start building the first frame, with max speed)
	if (hp <= 0.10000001 || (bt->etaFrame == -1 && !bt->buildTask)) {
		// unit was made this frame
		assert(maxAssignedBuildPower > 0);
//		float minTimeNeeded =  buildTime / maxAssignedBuildPower;
//		oldHP = hp;
	}

	if (hp > 0.11 && maxBuildPower > 0) {
		// building has started
		float minTimeNeeded =  buildTime / maxBuildPower;
		assert(minTimeNeeded > 0);
		float currentMaxE_usage = eNeed / minTimeNeeded;
//		float currentMaxM_usage = mNeed / minTimeNeeded;

		// find the delta HP from last frame, note that the first
		// 0.1 HP is a free loan that is payed at the end
		float deltaHP = hp - oldHP;

		if (hp == endHp)
			deltaHP += 0.1;

		if (deltaHP <= 0.0f) {
			// nanostalling
			deltaHP = 0.0001;
		}
		if (bt->etaFrame == -1 && !bt->buildTask)
			deltaHP -= 0.1;

		assert(deltaHP > 0);
		float eta2 = endHp * (1.0 - builtRatio) / deltaHP;

		if (bt->etaFrame == -1) {
			// started to make the unit now
			bt->startedRealBuildingFrame = frame;
			bt->etaFrame = -2;
			bt->hpSomeTimeAgo = hp;
			// deltaHP -= 0.1;

			if (!bt->buildTask) {
				bt->etaFrame = int(eta2 + frame);
			}
		}

		assert(eNeed > 0);
		assert(mNeed > 0);
		assert(currentMaxE_usage > 0);
		float usedE_ThisFrame = deltaHP / endHp * eNeed;
		float usedM_ThisFrame = deltaHP / endHp * mNeed;
//		float calcUsedE_ThisFrame = currentMaxE_usage / 30;
//		float currentBuildPower =  32.0 * maxBuildPower * (usedE_ThisFrame / currentMaxE_usage);
		constructionEnergy += usedE_ThisFrame;
		constructionMetal += usedM_ThisFrame;
		oldHP = hp;
		bt->hpLastFrame = hp;

		if ((frame - bt->startedRealBuildingFrame) % 16 == 0 && (bt->startedRealBuildingFrame +16) <= frame) {
			// the damage part needs testing
			float longDeltaHP = (hp + bt->damage) - bt->hpSomeTimeAgo;

			if (longDeltaHP <= 0) {
				// builder must have been pushed away and Spring says it still builds
				longDeltaHP = 0.000001;
			}

			// assert(longDeltaHP > 0);
			float longEta = endHp * (1.0 - builtRatio) / (longDeltaHP / 16.0);
			bt->etaFrame = int(longEta + frame + 1);
			bt->hpSomeTimeAgo = hp;
			bt->energyUsage =  longDeltaHP / endHp * eNeed;
			bt->metalUsage =  longDeltaHP / endHp * mNeed;
			// bt->damageSomeTimeAgo = bt->damage;
		}

		// HACK
		bt->economyUnitTracker->createFrame = bt->etaFrame;
	} else {
		// not started yet (unit moving the nano-emitter thing)
		// NOTE: the builder(s) might have been killed too...
		bt->hpLastFrame = hp;
	}
	

}


void CEconomyTracker::UnitCreated(int unit) {
	if(trackerOff)
		return;

	int frame = ai->cb->GetCurrentFrame();

	if (frame == 0) {
		// ignore the commander
		return;
	}

	EconomyUnitTracker* economyUnitTracker = new EconomyUnitTracker;
	economyUnitTracker->clear();
	economyUnitTracker->economyUnitId = unit;
	economyUnitTracker->createFrame = -frame;
	economyUnitTracker->alive = true;
	economyUnitTracker->category = GCAT(unit);
	economyUnitTracker->unitDef = ai->cb->GetUnitDef(unit);
	SetUnitDefDataInTracker(economyUnitTracker);
	underConstructionEconomyUnitTrackers.push_back(economyUnitTracker);


	// find it (slow++)
	bool found = false;
	for (int category = 0; category < LASTCATEGORY; category++ ) {
		for (list<BuildTask>::iterator i = ai->uh->BuildTasks[category].begin(); i != ai->uh->BuildTasks[category].end(); i++) {
			BuildTask bt = *i;

			if (bt.id == unit) {
				// add this new unit to the list
				BuildingTracker tracker;
				tracker.clear();
				tracker.economyUnitTracker = economyUnitTracker;
				tracker.buildTask = true;
				tracker.category = category;
				tracker.unitUnderConstruction = unit;
				allTheBuildingTrackers[category].push_front(tracker);
				found = true;
				break;
			}
		}
	}

	if (!found) {
		// it is made by a factory
		float3 unitPos = ai->cb->GetUnitPos(unit);
		int category = GCAT(unit);

		for (list<Factory>::iterator i = ai->uh->Factories.begin(); i != ai->uh->Factories.end(); i++) {
			Factory factory = *i;
			int factoryId = factory.id;
			// bad, no easy way to get the factory of the unit
			float3 factoryPos = ai->cb->GetUnitPos(factoryId);
			float distance = factoryPos.distance2D(unitPos);

			if (distance < 100) {
				BuildingTracker tracker;
				tracker.clear();
				tracker.economyUnitTracker = economyUnitTracker;
				tracker.category = category;
				tracker.unitUnderConstruction = unit;
				tracker.factory = factoryId;
				allTheBuildingTrackers[category].push_front(tracker);
				found = true;
				break;
			}
		}
	}

	if (!found) {
		// unit constructor not found?!
	}
}



void CEconomyTracker::SetUnitDefDataInTracker(EconomyUnitTracker* economyUnitTracker) {
	economyUnitTracker->unitDef = ai->cb->GetUnitDef(economyUnitTracker->economyUnitId);
	float energyProduction = 0;
	float metalProduction = 0;
	energyProduction += economyUnitTracker->unitDef->energyMake;
	metalProduction += economyUnitTracker->unitDef->metalMake;

	if (economyUnitTracker->unitDef->windGenerator > 0) {
		// it makes (some) power from wind
		int minWind = int(ai->cb->GetMinWind());
		int maxWind = int(ai->cb->GetMaxWind());
		energyProduction += ((minWind + maxWind) / 2.0);
	}

	// tidalGenerator?
	if (economyUnitTracker->unitDef->tidalGenerator > 0) {
		// NOTE: is this the power or a bool ?  and can it be negative ?
		// it makes (some) power from water
		energyProduction += ai->cb->GetTidalStrength();
	}

	economyUnitTracker->estimateEnergyChangeFromDefWhileOff = energyProduction / 2;
	economyUnitTracker->estimateMetalChangeFromDefWhileOff = metalProduction / 2;
	// add the ON state change
	energyProduction -= economyUnitTracker->unitDef->energyUpkeep;
	metalProduction -= economyUnitTracker->unitDef->metalUpkeep;

	if (economyUnitTracker->unitDef->isMetalMaker) {
		metalProduction += economyUnitTracker->unitDef->makesMetal;
	}

	if (economyUnitTracker->unitDef->extractsMetal) {
		// it's a mex: must find out what it will make later on (look at the metalMap spot data?)
		vector<float3> spots = ai->mm->VectoredSpots;
		float3 thisPos = ai->cb->GetUnitPos(economyUnitTracker->economyUnitId);
		bool foundMexSpot = false;

		for (vector<float3>::iterator i = spots.begin(); i != spots.end(); i++) {
			float distance = i->distance2D(thisPos);
			if (distance < 48) {
				// HACK
				float metalMakeFromThisSpot = i->y;
				metalMakeFromThisSpot *= economyUnitTracker->unitDef->extractsMetal;
				metalProduction += metalMakeFromThisSpot;
				foundMexSpot = true;
				break;
			}
		}
		assert(foundMexSpot);
		// metalProduction += conomyUnitTracker->def->makesMetal;
	}

	economyUnitTracker->estimateEnergyChangeFromDefWhileOn = energyProduction / 2;;
	economyUnitTracker->estimateMetalChangeFromDefWhileOn = metalProduction / 2;;
}



void CEconomyTracker::UnitFinished(int unit) {
	if (trackerOff)
		return;

	int frame = ai->cb->GetCurrentFrame();
	
	if (frame == 0) {
		// add the commander to a EconomyUnitTracker
		EconomyUnitTracker * economyUnitTracker = new EconomyUnitTracker;
		economyUnitTracker->clear();
		economyUnitTracker->economyUnitId = unit;
		economyUnitTracker->createFrame = frame;
		economyUnitTracker->alive = true;
		economyUnitTracker->category = GCAT(unit);
		economyUnitTracker->unitDef = ai->cb->GetUnitDef(unit);
		SetUnitDefDataInTracker(economyUnitTracker);
		newEconomyUnitTrackers.push_back(economyUnitTracker);
		return;
	}

	// move the new EconomyUnitTrackers
	bool found = false;
	list<EconomyUnitTracker*> removeList;
	for (list<EconomyUnitTracker*>::iterator i = underConstructionEconomyUnitTrackers.begin(); i != underConstructionEconomyUnitTrackers.end(); i++) {
		EconomyUnitTracker *bt = *i;
		if (bt->economyUnitId == unit) {
			 bt->createFrame = frame;
			assert(bt->alive);
			newEconomyUnitTrackers.push_back(bt);
			removeList.push_back(bt);
			found = true;
			break;
		}
	}

	assert(found);
	// remove them from underConstructionEconomyUnitTrackers
	for (list<EconomyUnitTracker*>::iterator i = removeList.begin(); i != removeList.end(); i++) {
		underConstructionEconomyUnitTrackers.remove(*i);
	}

	int category = ai->ut->GetCategory(unit);
	found = false;

	if (category != -1) {
		for (list<BuildingTracker>::iterator i = allTheBuildingTrackers[category].begin(); i != allTheBuildingTrackers[category].end(); i++) {
			BuildingTracker* bt = &*i;
			if (bt->unitUnderConstruction == unit) {
				updateUnitUnderConstruction(bt);
				found = true;
				allTheBuildingTrackers[category].erase(i);
				break;
			}
		}
		if (!found) {
			// unit not in a BuildingTracker?
		}
	}
}




void CEconomyTracker::UnitDestroyed(int unit) {
	if (trackerOff)
		return;

	assert(ai->cb->GetUnitDef(unit) != NULL);
	int frame = ai->cb->GetCurrentFrame();

	// move the dead EconomyUnitTracker
	bool found = false;
	for (list<EconomyUnitTracker*>::iterator i = activeEconomyUnitTrackers.begin(); i != activeEconomyUnitTrackers.end(); i++) {
		EconomyUnitTracker *bt = *i;
		if (bt->economyUnitId == unit) {
			assert(bt->alive);
			bt->alive = false;
			bt->dieFrame = frame;
			deadEconomyUnitTrackers.push_back(bt);
			activeEconomyUnitTrackers.remove(bt);
			// was alive for (frame - bt->createFrame) frames
			found = true;
			break;
		}
	}
	if (!found) {
		for (list<EconomyUnitTracker*>::iterator i = underConstructionEconomyUnitTrackers.begin(); i != underConstructionEconomyUnitTrackers.end(); i++) {
			EconomyUnitTracker *bt = *i;
			if (bt->economyUnitId == unit) {
				assert(bt->alive);
				bt->alive = false;
				bt->dieFrame = frame;
				deadEconomyUnitTrackers.push_back(bt);
				underConstructionEconomyUnitTrackers.remove(bt);
				// was still under construction
				found = true;
				break;
			}
		}
	}
	if (!found) {
		for (list<EconomyUnitTracker*>::iterator i = newEconomyUnitTrackers.begin(); i != newEconomyUnitTrackers.end(); i++) {
			EconomyUnitTracker *bt = *i;
			if (bt->economyUnitId == unit) {
				assert(bt->alive);
				bt->alive = false;
				bt->dieFrame = frame;
				deadEconomyUnitTrackers.push_back(bt);
				newEconomyUnitTrackers.remove(bt);
				// was alive for (frame - bt->createFrame) frames and never managed to do anything
				found = true;
				break;
			}
		}
	}

	// if unit was being built, remove it
	if (ai->cb->UnitBeingBuilt(unit)) {
		int category = ai->ut->GetCategory(unit);
		bool found = false;

		if (category != -1) {
			for (list<BuildingTracker>::iterator i = allTheBuildingTrackers[category].begin(); i != allTheBuildingTrackers[category].end(); i++) {
				BuildingTracker *bt = &*i;
				if (bt->unitUnderConstruction == unit) {
					// hp will be negative if this re-enabled
					// updateUnitUnderConstruction(bt);
					found = true;
					allTheBuildingTrackers[category].erase(i);
					break;
				}
			}
			if (!found) {
				// unit not in a BuildingTracker?
			}
		}
	}
}



void CEconomyTracker::UnitDamaged(int unit, float damage) {
	if (trackerOff)
		return;

	if (ai->cb->UnitBeingBuilt(unit)) {
		int category = ai->ut->GetCategory(unit);
		bool found = false;

		if (category != -1) {
			for (list<BuildingTracker>::iterator i = allTheBuildingTrackers[category].begin(); i != allTheBuildingTrackers[category].end(); i++) {
				BuildingTracker *bt = &*i;
				if (bt->unitUnderConstruction == unit) {
					bt->damage += damage;
					bt->hpLastFrame -= damage;
					found = true;
					break;
				}
			}
			if (!found) {
				// unit not in a BuildingTracker?
			}
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -