CFeature* CFeatureHandler::CreateWreckage(const float3& pos, const string& name, float rot, int facing, int iter, int team, int allyteam, bool emitSmoke, const UnitDef* udef, const float3& speed) { const FeatureDef* fd; const string* defname = &name; int i = iter; do { if (defname->empty()) return NULL; fd = GetFeatureDef(*defname); if (!fd) return NULL; defname = &(fd->deathFeature); } while (--i > 0); if (luaRules && !luaRules->AllowFeatureCreation(fd, team, pos)) return NULL; if (!fd->modelname.empty()) { CFeature* f = new CFeature(); if (fd->resurrectable == 0 || (iter > 1 && fd->resurrectable < 0)) { f->Initialize(pos, fd, (short int) rot, facing, team, allyteam, NULL, speed, emitSmoke ? fd->smokeTime : 0); } else { f->Initialize(pos, fd, (short int) rot, facing, team, allyteam, udef, speed, emitSmoke ? fd->smokeTime : 0); } return f; } return NULL; }
CObject_pointer<CFeature>* FeatureLoaderLoadFeature( string name, float3 pos, int team ) { FeatureDef *def = featureHandler->GetFeatureDef(name); CFeature* feature = new CFeature(); feature->Initialize( pos,def,0, 0, team,"" ); return new CObject_pointer<CFeature>(feature); }
CFeature* CFeatureHandler::CreateWreckage(const float3& pos, const std::string& name, float rot, int facing, int iter, int team, int allyteam, bool emitSmoke, std::string fromUnit, const float3& speed) { const FeatureDef* fd; const std::string* defname = &name; int i = iter; do { if (name.empty()) return NULL; fd = GetFeatureDef(*defname); if (!fd) return NULL; defname = &(fd->deathFeature); } while (--i > 0); if (luaRules && !luaRules->AllowFeatureCreation(fd, team, pos)) return NULL; if (!fd->modelname.empty()) { if (fd->resurrectable==0 || (iter>1 && fd->resurrectable<0)) fromUnit = ""; CFeature* f = new CFeature; f->Initialize(pos, fd, (short int) rot, facing, team, fromUnit, speed); // allow area-reclaiming wrecks of all units, including your own (they set allyteam = -1) f->allyteam = allyteam; if (emitSmoke && fd->blocking) f->emitSmokeTime = fd->smokeTime; return f; } return NULL; }
CFeature* CFeatureHandler::CreateWreckage(const float3& pos, const std::string& name, float rot, int facing, int iter, int team, int allyteam, bool emitSmoke, std::string fromUnit, const float3& speed) { ASSERT_SYNCED_MODE; if (name.empty()) { return NULL; } const FeatureDef* fd = GetFeatureDef(name); if (!fd) { return NULL; } if (iter > 1) { return CreateWreckage(pos, fd->deathFeature, rot, facing, iter - 1, team, allyteam, emitSmoke, "", speed); } else { if (luaRules && !luaRules->AllowFeatureCreation(fd, team, pos)) { return NULL; } if (!fd->modelname.empty()) { CFeature* f = SAFE_NEW CFeature; f->Initialize(pos, fd, (short int) rot, facing, team, fromUnit, speed); // allow area-reclaiming wrecks of all units, including your own (they set allyteam = -1) f->allyteam = allyteam; if (emitSmoke && f->blocking) f->emitSmokeTime = 300; return f; } } return NULL; }
void CFeatureHandler::LoadFeaturesFromMap(bool onlyCreateDefs) { // add default tree and geo FeatureDefs defined by the map const int numFeatureTypes = readmap->GetNumFeatureTypes(); for (int a = 0; a < numFeatureTypes; ++a) { const string& name = StringToLower(readmap->GetFeatureTypeName(a)); if (GetFeatureDef(name, false) == NULL) { if (name.find("treetype") != string::npos) { AddFeatureDef(name, CreateDefaultTreeFeatureDef(name)); } else if (name.find("geovent") != string::npos) { AddFeatureDef(name, CreateDefaultGeoFeatureDef(name)); } else { LOG_L(L_ERROR, "[%s] unknown map feature type \"%s\"", __FUNCTION__, name.c_str()); } } } // add a default geovent FeatureDef if the map did not if (GetFeatureDef("geovent", false) == NULL) { AddFeatureDef("geovent", CreateDefaultGeoFeatureDef("geovent")); } if (!onlyCreateDefs) { // create map-specified feature instances const int numFeatures = readmap->GetNumFeatures(); MapFeatureInfo* mfi = new MapFeatureInfo[numFeatures]; readmap->GetFeatureInfo(mfi); for (int a = 0; a < numFeatures; ++a) { const string& name = StringToLower(readmap->GetFeatureTypeName(mfi[a].featureType)); map<string, const FeatureDef*>::iterator def = featureDefs.find(name); if (def == featureDefs.end()) { LOG_L(L_ERROR, "Unknown feature named '%s'", name.c_str()); continue; } const float ypos = ground->GetHeightReal(mfi[a].pos.x, mfi[a].pos.z); const float3 fpos = float3(mfi[a].pos.x, ypos, mfi[a].pos.z); const FeatureDef* fdef = def->second; CFeature* f = new CFeature(); f->Initialize(fpos, fdef, (short int) mfi[a].rotation, 0, -1, -1, NULL); } delete[] mfi; } }
void CFeatureHandler::LoadSaveFeatures(CLoadSaveInterface* file, bool loading) { if(loading) freeIDs.clear(); for(int a=0;a<MAX_FEATURES;++a){ bool exists=!!features[a]; file->lsBool(exists); if(exists){ if(loading){ overrideId=a; float3 pos; file->lsFloat3(pos); string def; file->lsString(def); if(featureDefs.find(def)==featureDefs.end()) GetFeatureDef(def); short rotation; file->lsShort(rotation); string fromUnit; file->lsString(fromUnit); CFeature* f = SAFE_NEW CFeature; f->Initialize (pos,featureDefs[def],rotation,0,-1,fromUnit); } else { file->lsFloat3(features[a]->pos); file->lsString(features[a]->def->myName); file->lsShort(features[a]->heading); file->lsString(features[a]->createdFromUnit); } CFeature* f=features[a]; file->lsFloat(f->health); file->lsFloat(f->reclaimLeft); file->lsInt(f->allyteam); } else { if(loading) freeIDs.push_back(a); } } overrideId=-1; }
// FOR SYNCED MESSAGES void CGame::ActionReceived(const Action& action, int playernum) { if (action.command == "cheat") { SetBoolArg(gs->cheatEnabled, action.extra); if (gs->cheatEnabled) logOutput.Print("Cheating!"); else logOutput.Print("No more cheating"); } else if (action.command == "nohelp") { SetBoolArg(gs->noHelperAIs, action.extra); selectedUnits.PossibleCommandChange(NULL); logOutput.Print("LuaUI control is %s", gs->noHelperAIs ? "disabled" : "enabled"); } else if (action.command == "nospecdraw") { bool buf; SetBoolArg(buf, action.extra); inMapDrawer->SetSpecMapDrawingAllowed(buf); } else if (action.command == "godmode") { if (!gs->cheatEnabled) logOutput.Print("godmode requires /cheat"); else { SetBoolArg(gs->godMode, action.extra); CLuaUI::UpdateTeams(); if (gs->godMode) { logOutput.Print("God Mode Enabled"); } else { logOutput.Print("God Mode Disabled"); } CPlayer::UpdateControlledTeams(); } } else if (action.command == "globallos") { if (!gs->cheatEnabled) { logOutput.Print("globallos requires /cheat"); } else { SetBoolArg(gs->globalLOS, action.extra); if (gs->globalLOS) { logOutput.Print("Global LOS Enabled"); } else { logOutput.Print("Global LOS Disabled"); } } } else if (action.command == "nocost" && gs->cheatEnabled) { if (unitDefHandler->ToggleNoCost()) { logOutput.Print("Everything is for free!"); } else { logOutput.Print("Everything costs resources again!"); } } else if (action.command == "give" && gs->cheatEnabled) { std::string s = "give "; //FIXME lazyness s += action.extra; // .give [amount] <unitName> [team] <@x,y,z> const vector<string> &args = CSimpleParser::Tokenize(s, 0); if (args.size() < 3) { logOutput.Print("Someone is spoofing invalid .give messages!"); return; } float3 pos; if (sscanf(args[args.size() - 1].c_str(), "@%f,%f,%f", &pos.x, &pos.y, &pos.z) != 3) { logOutput.Print("Someone is spoofing invalid .give messages!"); return; } int amount = 1; int team = playerHandler->Player(playernum)->team; int amountArgIdx = -1; int teamArgIdx = -1; if (args.size() == 5) { amountArgIdx = 1; teamArgIdx = 3; } else if (args.size() == 4) { if (args[1].find_first_not_of("0123456789") == string::npos) { amountArgIdx = 1; } else { teamArgIdx = 2; } } if (amountArgIdx >= 0) { const string& amountStr = args[amountArgIdx]; amount = atoi(amountStr.c_str()); if ((amount < 0) || (amountStr.find_first_not_of("0123456789") != string::npos)) { logOutput.Print("Bad give amount: %s", amountStr.c_str()); return; } } if (teamArgIdx >= 0) { const string& teamStr = args[teamArgIdx]; team = atoi(teamStr.c_str()); if ((!teamHandler->IsValidTeam(team)) || (teamStr.find_first_not_of("0123456789") != string::npos)) { logOutput.Print("Bad give team: %s", teamStr.c_str()); return; } } const string unitName = (amountArgIdx >= 0) ? args[2] : args[1]; if (unitName == "all") { // player entered ".give all" int numRequestedUnits = unitDefHandler->unitDefs.size() - 1; /// defid=0 is not valid int currentNumUnits = teamHandler->Team(team)->units.size(); int sqSize = (int) streflop::ceil(streflop::sqrt((float) numRequestedUnits)); // make sure team unit-limit not exceeded if ((currentNumUnits + numRequestedUnits) > uh->MaxUnitsPerTeam()) { numRequestedUnits = uh->MaxUnitsPerTeam() - currentNumUnits; } // make sure square is entirely on the map float sqHalfMapSize = sqSize / 2 * 10 * SQUARE_SIZE; pos.x = std::max(sqHalfMapSize, std::min(pos.x, float3::maxxpos - sqHalfMapSize - 1)); pos.z = std::max(sqHalfMapSize, std::min(pos.z, float3::maxzpos - sqHalfMapSize - 1)); for (int a = 1; a <= numRequestedUnits; ++a) { float posx = pos.x + (a % sqSize - sqSize / 2) * 10 * SQUARE_SIZE; float posz = pos.z + (a / sqSize - sqSize / 2) * 10 * SQUARE_SIZE; float3 pos2 = float3(posx, pos.y, posz); const UnitDef* ud = unitDefHandler->GetUnitDefByID(a); if (ud) { const CUnit* unit = unitLoader->LoadUnit(ud, pos2, team, false, 0, NULL); if (unit) { unitLoader->FlattenGround(unit); } } } } else if (!unitName.empty()) { int numRequestedUnits = amount; int currentNumUnits = teamHandler->Team(team)->units.size(); if (currentNumUnits >= uh->MaxUnitsPerTeam()) { LogObject() << "Unable to give any more units to team " << team << "(current: " << currentNumUnits << ", max: " << uh->MaxUnits() << ")"; return; } // make sure team unit-limit is not exceeded if ((currentNumUnits + numRequestedUnits) > uh->MaxUnitsPerTeam()) { numRequestedUnits = uh->MaxUnitsPerTeam() - currentNumUnits; } const UnitDef* unitDef = unitDefHandler->GetUnitDefByName(unitName); if (unitDef != NULL) { int xsize = unitDef->xsize; int zsize = unitDef->zsize; int squareSize = (int) streflop::ceil(streflop::sqrt((float) numRequestedUnits)); int total = numRequestedUnits; float3 minpos = pos; minpos.x -= ((squareSize - 1) * xsize * SQUARE_SIZE) / 2; minpos.z -= ((squareSize - 1) * zsize * SQUARE_SIZE) / 2; for (int z = 0; z < squareSize; ++z) { for (int x = 0; x < squareSize && total > 0; ++x) { float minposx = minpos.x + x * xsize * SQUARE_SIZE; float minposz = minpos.z + z * zsize * SQUARE_SIZE; const float3 upos(minposx, minpos.y, minposz); const CUnit* unit = unitLoader->LoadUnit(unitDef, upos, team, false, 0, NULL); if (unit) { unitLoader->FlattenGround(unit); } --total; } } logOutput.Print("Giving %i %s to team %i", numRequestedUnits, unitName.c_str(), team); } else { int allyteam = -1; if (teamArgIdx < 0) { team = -1; // default to world features allyteam = -1; } else { allyteam = teamHandler->AllyTeam(team); } const FeatureDef* featureDef = featureHandler->GetFeatureDef(unitName); if (featureDef) { int xsize = featureDef->xsize; int zsize = featureDef->zsize; int squareSize = (int) streflop::ceil(streflop::sqrt((float) numRequestedUnits)); int total = amount; // FIXME -- feature count limit? float3 minpos = pos; minpos.x -= ((squareSize - 1) * xsize * SQUARE_SIZE) / 2; minpos.z -= ((squareSize - 1) * zsize * SQUARE_SIZE) / 2; for (int z = 0; z < squareSize; ++z) { for (int x = 0; x < squareSize && total > 0; ++x) { float minposx = minpos.x + x * xsize * SQUARE_SIZE; float minposz = minpos.z + z * zsize * SQUARE_SIZE; float minposy = ground->GetHeightReal(minposx, minposz); const float3 upos(minposx, minposy, minposz); CFeature* feature = new CFeature(); // Initialize() adds the feature to the FeatureHandler -> no memory-leak feature->Initialize(upos, featureDef, 0, 0, team, allyteam, ""); --total; } } logOutput.Print("Giving %i %s (feature) to team %i", numRequestedUnits, unitName.c_str(), team); } else { logOutput.Print(unitName + " is not a valid unitname"); } } } } else if (action.command == "destroy" && gs->cheatEnabled) { std::stringstream ss(action.extra); logOutput.Print("Killing units: %s", action.extra.c_str()); do { unsigned id; ss >> id; if (!ss) break; if (id >= uh->units.size()) continue; if (uh->units[id] == NULL) continue; uh->units[id]->KillUnit(false, false, 0); } while (true); }
void CFeatureHandler::LoadFeaturesFromMap(CFileHandler* file,bool onlyCreateDefs) { file->Seek(readmap->header.featurePtr); MapFeatureHeader fh; READ_MAPFEATUREHEADER(fh, file); if(file->Eof()){ info->AddLine("No features in map file?"); return; } string* mapids=new string[fh.numFeatureType]; for(int a=0;a<fh.numFeatureType;++a){ char c; file->Read(&c,1); while(c){ mapids[a]+=c; file->Read(&c,1); } string name=mapids[a]; if(name.find("TreeType")!=string::npos){ FeatureDef* fd=new FeatureDef; fd->blocking=1; fd->burnable=true; fd->destructable=1; fd->drawType=DRAWTYPE_TREE; fd->modelType=atoi(name.substr(8).c_str()); fd->energy=250; fd->metal=0; fd->maxHealth=5; fd->radius=20; fd->xsize=2; fd->ysize=2; fd->myName=name; fd->mass=20; featureDefs[name]=fd; } else if(name.find("GeoVent")!=string::npos){ FeatureDef* fd=new FeatureDef; fd->blocking=0; fd->burnable=0; fd->destructable=0; fd->geoThermal=1; fd->drawType=DRAWTYPE_NONE; //geos are drawn into the ground texture and emit smoke to be visible fd->modelType=0; fd->energy=0; fd->metal=0; fd->maxHealth=0; fd->radius=0; fd->xsize=0; fd->ysize=0; fd->myName=name; fd->mass=100000; featureDefs[name]=fd; } else if(wreckParser.SectionExist(name)){ GetFeatureDef(name); } else { info->AddLine("Unknown feature type %s",name.c_str()); } } if(!onlyCreateDefs){ for(int a=0;a<fh.numFeatures;++a){ MapFeatureStruct ffs; READ_MAPFEATURESTRUCT(ffs, file); string name=mapids[ffs.featureType]; ffs.ypos=ground->GetHeight2(ffs.xpos,ffs.zpos); CFeature *f = new CFeature; f->Initialize (float3(ffs.xpos,ffs.ypos,ffs.zpos),featureDefs[name],(short int)ffs.rotation,-1,""); } } delete[] mapids; }
void CUnitLoader::GiveUnits(const std::string& objectName, float3 pos, int amount, int team, int featureAllyTeam) { const CTeam* receivingTeam = teamHandler->Team(team); if (objectName == "all") { unsigned int numRequestedUnits = unitDefHandler->unitDefs.size() - 1; /// defid=0 is not valid unsigned int currentNumUnits = receivingTeam->units.size(); // make sure team unit-limit is not exceeded if ((currentNumUnits + numRequestedUnits) > receivingTeam->maxUnits) { numRequestedUnits = receivingTeam->maxUnits - currentNumUnits; } // make sure square is entirely on the map const int sqSize = math::ceil(math::sqrt((float) numRequestedUnits)); const float sqHalfMapSize = sqSize / 2 * 10 * SQUARE_SIZE; pos.x = std::max(sqHalfMapSize, std::min(pos.x, float3::maxxpos - sqHalfMapSize - 1)); pos.z = std::max(sqHalfMapSize, std::min(pos.z, float3::maxzpos - sqHalfMapSize - 1)); for (int a = 1; a <= numRequestedUnits; ++a) { Watchdog::ClearPrimaryTimers(); // the other thread may be waiting for a mutex held by this one, triggering hang detection const float px = pos.x + (a % sqSize - sqSize / 2) * 10 * SQUARE_SIZE; const float pz = pos.z + (a / sqSize - sqSize / 2) * 10 * SQUARE_SIZE; const float3 unitPos = float3(px, ground->GetHeightReal(px, pz), pz); const UnitDef* unitDef = unitDefHandler->GetUnitDefByID(a); if (unitDef != NULL) { const CUnit* unit = LoadUnit(unitDef, unitPos, team, false, 0, NULL); if (unit != NULL) { FlattenGround(unit); } } } } else { unsigned int numRequestedUnits = amount; unsigned int currentNumUnits = receivingTeam->units.size(); if (receivingTeam->AtUnitLimit()) { LOG_L(L_WARNING, "[%s] unable to give more units to team %d (current: %u, team limit: %u, global limit: %u)", __FUNCTION__, team, currentNumUnits, receivingTeam->maxUnits, uh->MaxUnits() ); return; } // make sure team unit-limit is not exceeded if ((currentNumUnits + numRequestedUnits) > receivingTeam->maxUnits) { numRequestedUnits = receivingTeam->maxUnits - currentNumUnits; } const UnitDef* unitDef = unitDefHandler->GetUnitDefByName(objectName); const FeatureDef* featureDef = featureHandler->GetFeatureDef(objectName, false); if (unitDef == NULL && featureDef == NULL) { LOG_L(L_WARNING, "[%s] %s is not a valid object-name", __FUNCTION__, objectName.c_str()); return; } if (unitDef != NULL) { const int xsize = unitDef->xsize; const int zsize = unitDef->zsize; const int squareSize = math::ceil(math::sqrt((float) numRequestedUnits)); const float3 squarePos = float3( pos.x - (((squareSize - 1) * xsize * SQUARE_SIZE) / 2), pos.y, pos.z - (((squareSize - 1) * zsize * SQUARE_SIZE) / 2) ); int total = numRequestedUnits; for (int z = 0; z < squareSize; ++z) { for (int x = 0; x < squareSize && total > 0; ++x) { const float px = squarePos.x + x * xsize * SQUARE_SIZE; const float pz = squarePos.z + z * zsize * SQUARE_SIZE; const float3 unitPos = float3(px, ground->GetHeightReal(px, pz), pz); Watchdog::ClearPrimaryTimers(); const CUnit* unit = LoadUnit(unitDef, unitPos, team, false, 0, NULL); if (unit != NULL) { FlattenGround(unit); } --total; } } LOG("[%s] spawned %i %s unit(s) for team %i", __FUNCTION__, numRequestedUnits, objectName.c_str(), team); } if (featureDef != NULL) { if (featureAllyTeam < 0) { team = -1; // default to world features } const int xsize = featureDef->xsize; const int zsize = featureDef->zsize; const int squareSize = math::ceil(math::sqrt((float) numRequestedUnits)); const float3 squarePos = float3( pos.x - (((squareSize - 1) * xsize * SQUARE_SIZE) / 2), pos.y, pos.z - (((squareSize - 1) * zsize * SQUARE_SIZE) / 2) ); int total = amount; // FIXME -- feature count limit? for (int z = 0; z < squareSize; ++z) { for (int x = 0; x < squareSize && total > 0; ++x) { const float px = squarePos.x + x * xsize * SQUARE_SIZE; const float pz = squarePos.z + z * zsize * SQUARE_SIZE; const float3 featurePos = float3(px, ground->GetHeightReal(px, pz), pz); Watchdog::ClearPrimaryTimers(); CFeature* feature = new CFeature(); // Initialize() adds the feature to the FeatureHandler -> no memory-leak feature->Initialize(featurePos, featureDef, 0, 0, team, featureAllyTeam, NULL); --total; } } LOG("[%s] spawned %i %s feature(s) for team %i", __FUNCTION__, numRequestedUnits, objectName.c_str(), team); } } }