spawnscript.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 172 行

CPP
172
字号
#include "StdAfx.h"
#include "SpawnScript.h"
#include <fstream>
#include "TdfParser.h"
#include "Sim/Units/UnitLoader.h"
#include "Sim/Units/Unit.h"
#include "Sim/Units/UnitHandler.h"
#include "Game/Team.h"
#include <set>
#include "Sim/Units/CommandAI/Command.h"
#include "Sim/Units/CommandAI/CommandAI.h"
#include "Map/ReadMap.h"
#include "mmgr.h"

extern std::string stupidGlobalMapname;

CSpawnScript::CSpawnScript(bool _autonomous) :
		CScript(std::string(_autonomous ? "Random enemies 2" : "Random enemies")),
		autonomous(_autonomous),
		frameOffset(0)
{
}

CSpawnScript::~CSpawnScript()
{
}

void CSpawnScript::Update()
{
	switch(gs->frameNum){
	case 0:
		LoadSpawns();

		TdfParser p("gamedata/sidedata.tdf");
		string s0=p.SGetValueDef("armcom","side0\\commander");
		string s1=p.SGetValueDef("corcom","side1\\commander");

		TdfParser p2;
		CReadMap::OpenTDF (stupidGlobalMapname, p2);

		float x0,z0;
		p2.GetDef(x0,"1000","MAP\\TEAM0\\StartPosX");
		p2.GetDef(z0,"1000","MAP\\TEAM0\\StartPosZ");

		// Set the TEAM0 startpos as spawnpos if we're supposed to be
		// autonomous, load the commander for the player if not.
		if (autonomous) spawnPos.push_back(float3(x0,80,z0));
		else unitLoader.LoadUnit(s0,float3(x0,80,z0),0,false,0,NULL);

		p2.GetDef(x0,"1000","MAP\\TEAM1\\StartPosX");
		p2.GetDef(z0,"1000","MAP\\TEAM1\\StartPosZ");
		spawnPos.push_back(float3(x0,80,z0));

		p2.GetDef(x0,"1000","MAP\\TEAM2\\StartPosX");
		p2.GetDef(z0,"1000","MAP\\TEAM2\\StartPosZ");
		spawnPos.push_back(float3(x0,80,z0));

		p2.GetDef(x0,"1000","MAP\\TEAM3\\StartPosX");
		p2.GetDef(z0,"1000","MAP\\TEAM3\\StartPosZ");
		spawnPos.push_back(float3(x0,80,z0));
	}

	if(!spawns.empty()){
		while(curSpawn->frame+frameOffset<gs->frameNum){
			int num = gs->randInt() % spawnPos.size();
			int team = autonomous ? (num & 1) : 1;
			float3 pos;
			float dist=200;
			CFeature* feature;
			do {
				pos=spawnPos[num]+gs->randVector()*dist;
				dist*=1.05f;
			} while (dist < 500 && uh->TestUnitBuildSquare(BuildInfo(curSpawn->name,pos,0),feature,team) != 2);

			// Ignore unit if it really doesn't fit.
			// (within 18 tries, 200*1.05f^18 < 500 < 200*1.05f^19)
			if (dist < 500) {
				CUnit* u = unitLoader.LoadUnit(curSpawn->name, pos, team, false, 0, NULL);

				Unit unit;
				unit.id=u->id;
				unit.target=-1;
				unit.team=team;
				myUnits.push_back(unit);
				if(myUnits.size()==1)
					curUnit=myUnits.begin();
			}

			++curSpawn;
			if(curSpawn==spawns.end()){
				curSpawn=spawns.begin();
				frameOffset+=spawns.back().frame;
			}
		}
	}

	if(!myUnits.empty() && !gs->Team(1 - curUnit->team)->units.empty()) {
		if(uh->units[curUnit->id]){
			if(curUnit->target<0 || uh->units[curUnit->target]==0){
				// We can't rely on the ordering of units in a std::set<CUnit*>,
				// because they're sorted on memory address. Hence we must first
				// build a set of IDs and then pick an unit from that.
				// This guarantees the script doesn't desync in multiplayer games.
				int num = gs->randInt() % gs->Team(1 - curUnit->team)->units.size();
				std::set<int> unitids;
				CUnitSet* tu = &gs->Team(1 - curUnit->team)->units;
				for (CUnitSet::iterator u = tu->begin(); u != tu->end(); ++u)
					unitids.insert((*u)->id);
				std::set<int>::iterator ui = unitids.begin();
				for(int a=0;a<num;++a)
					++ui;
				curUnit->target=(*ui);
				curUnit->lastTargetPos.x=-500;
			}
			float3 pos=uh->units[curUnit->target]->pos;
			if(pos.distance2D(curUnit->lastTargetPos)>100){
				curUnit->lastTargetPos=pos;
				Command c;
				c.id=CMD_PATROL;
				c.options=0;
				c.params.push_back(pos.x);
				c.params.push_back(pos.y);
				c.params.push_back(pos.z);
				uh->units[curUnit->id]->commandAI->GiveCommand(c);
			}
			curUnit++;
		} else {
			curUnit=myUnits.erase(curUnit);
		}
		if(curUnit==myUnits.end())
			curUnit=myUnits.begin();
	}
}

void CSpawnScript::LoadSpawns()
{
	CFileHandler file("spawn.txt");

	while(file.FileExists() && !file.Eof()){

		Spawn s;
		s.frame=atoi(LoadToken(file).c_str());
		s.name=LoadToken(file).c_str();

		if(s.name.empty())
			break;

		spawns.push_back(s);
	}
	curSpawn=spawns.begin();
}

std::string CSpawnScript::LoadToken(CFileHandler& file)
{
	string s;
	char c;

	while (!file.Eof()) {
		file.Read(&c,1);
		if(c>='0' && c<='z')
			break;
	}
	s += c;
	while (!file.Eof()) {
		file.Read(&c,1);
		if(c<'0' || c>'z')
			return s;
		s+=c;
	}
	return s;
}

⌨️ 快捷键说明

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