void ReadTowns() { ntowns=0; char c; while(!isnum(c=getchar())) { while((c=getchar())!='\n'); } ungetc(c, stdin); int id; float x, y; while(scanf("%d", &id)&&!feof(stdin)) { scanf("%f%f", &x, &y); ntowns++; towns.push_back(Town(x, y)); } }
bool IOMapOTMM::loadMap(Map& map, NodeFileReadHandle& f, const FileName& identifier, bool showdialog) { BinaryNode* root = f.getRootNode(); if(!root) { error(wxT("Could not read root node.")); return false; } root->skip(1); // Skip the type byte uint8_t u8; uint16_t u16; uint32_t u32; if(!root->getU32(u32) || u32 != 1) { // Version error(wxT("Unsupported or damaged map version.")); return false; } if(!root->getU16(u16)) { error(wxT("Could not read root header.")); return false; } map.width = u16; if(!root->getU16(u16)) { error(wxT("Could not read root header.")); return false; } map.height = u16; if(!root->getU32(u32) || u32 > (unsigned long)item_db.MajorVersion) { // OTB major version if(queryUser(wxT("Map error"), wxT("The loaded map appears to be a items.otb format that deviates from the items.otb loaded by the editor. Do you still want to attempt to load the map?"))) { warning(wxT("Unsupported or damaged map version")); } else { error(wxT("Outdated items.otb, could not load map.")); return false; } } if(!root->getU32(u32) || u32 > (unsigned long)item_db.MinorVersion) { // OTB minor version warning(wxT("The editor needs an updated items.otb version.")); } BinaryNode* mapHeaderNode = root->getChild(); if(mapHeaderNode == NULL || !mapHeaderNode->getByte(u8) || u8 != OTMM_MAP_DATA) { error(wxT("Could not get root child node. Cannot recover from fatal error!")); return false; } int nodes_loaded = 0; BinaryNode* mapNode = mapHeaderNode->getChild(); if(mapNode) do { ++nodes_loaded; if(showdialog && nodes_loaded % 15 == 0) { gui.SetLoadDone(int(100.0 * f.tell() / f.size())); } uint8_t node_type; if(!mapNode->getByte(node_type)) { warning(wxT("Invalid map node")); continue; } switch(node_type) { case OTMM_EDITOR: { } break; case OTMM_DESCRIPTION: { std::string desc; mapNode->getString(desc); map.setMapDescription(desc); } break; case OTMM_TILE_DATA: { BinaryNode* tileNode = mapNode->getChild(); if(tileNode) do { Tile* tile = NULL; uint8_t tile_type; if(!tileNode->getByte(tile_type)) { warning(wxT("Invalid tile type")); continue; } if(tile_type != OTMM_TILE && tile_type != OTMM_HOUSETILE) { warning(wxT("Unknown type of tile node")); continue; } uint16_t x_offset, y_offset; uint8_t z_offset; if(!tileNode->getU16(x_offset) || !tileNode->getU16(y_offset) || !tileNode->getU8(z_offset) ) { warning(wxT("Could not read position of tile")); continue; } const Position pos(x_offset, y_offset, z_offset); if(map.getTile(pos)) { warning(wxT("Duplicate tile at %d:%d:%d, discarding duplicate"), pos.x, pos.y, pos.z); continue; } tile = map.allocator(pos); House* house = NULL; if(tile_type == OTMM_HOUSETILE) { uint32_t house_id; if(!tileNode->getU32(house_id)) { warning(wxT("House tile without house data, discarding tile")); continue; } if(house_id) { house = map.houses.getHouse(house_id); if(!house) { house = newd House(map); house->id = house_id; map.houses.addHouse(house); } } else { warning(wxT("Invalid house id from tile %d:%d:%d"), pos.x, pos.y, pos.z); } } uint16_t ground_id; tileNode->getU16(ground_id); if(ground_id != 0) { tile->addItem(Item::Create(ground_id)); } uint8_t attribute; while(tileNode->getU8(attribute)) { switch(attribute) { case OTMM_ATTR_TILE_FLAGS: { uint32_t flags = 0; if(!tileNode->getU32(flags)) { warning(wxT("Invalid tile flags of tile on %d:%d:%d"), pos.x, pos.y, pos.z); } tile->setMapFlags(flags); } break; default: { warning(wxT("Unknown tile attribute at %d:%d:%d"), pos.x, pos.y, pos.z); } break; } } BinaryNode* itemNode = tileNode->getChild(); if(itemNode) do { Item* item = NULL; uint8_t item_type; if(!itemNode->getByte(item_type)) { warning(wxT("Unknown item type %d:%d:%d"), pos.x, pos.y, pos.z); continue; } if(item_type == OTMM_ITEM) { item = Item::Create_OTMM(*this, itemNode); if(item) { if(item->unserializeItemNode_OTMM(*this, itemNode) == false) { warning(wxT("Couldn't unserialize item attributes at %d:%d:%d"), pos.x, pos.y, pos.z); } tile->addItem(item); } } else { warning(wxT("Unknown type of tile child node")); } } while(itemNode->advance()); tile->update(); if(house) { house->addTile(tile); } map.setTile(pos, tile); } while(tileNode->advance()); } break; case OTMM_SPAWN_DATA: { BinaryNode* spawnNode = mapNode->getChild(); if(spawnNode) do { uint8_t spawn_type; if(!spawnNode->getByte(spawn_type)) { warning(wxT("Could not read spawn type.")); continue; } if(spawn_type != OTMM_SPAWN_AREA) { warning(wxT("Invalid spawn type.")); continue; } // Read position uint16_t spawn_x, spawn_y; uint8_t spawn_z; uint32_t radius; if(!spawnNode->getU16(spawn_x) || !spawnNode->getU16(spawn_y) || !spawnNode->getU8(spawn_z) ) { warning(wxT("Could not read spawn position.")); continue; } const Position spawnpos(spawn_x, spawn_y, spawn_z); // Read radius if(!spawnNode->getU32(radius)) { warning(wxT("Could not read spawn radius.")); continue; } // Adjust radius radius = min(radius, uint32_t(settings.getInteger(Config::MAX_SPAWN_RADIUS))); // Create and assign spawn Tile* spawn_tile = map.getTile(spawnpos); if(spawn_tile && spawn_tile->spawn) { warning(wxT("Duplicate spawn on position %d:%d:%d\n"), spawn_tile->getX(), spawn_tile->getY(), spawn_tile->getZ()); continue; } Spawn* spawn = newd Spawn(radius); if(!spawn_tile) { spawn_tile = map.allocator(spawnpos); map.setTile(spawnpos, spawn_tile); } spawn_tile->spawn = spawn; map.addSpawn(spawn_tile); // Read any creatures associated with the spawn BinaryNode* creatureNode = spawnNode->getChild(); if(creatureNode) do { uint8_t creature_type; if(!creatureNode->getByte(creature_type)) { warning(wxT("Could not read type of creature node.")); continue; } bool isNPC; std::string name; uint32_t spawntime = 0; // Only applicable for monsters if(creature_type == OTMM_NPC) { isNPC = true; if(!creatureNode->getString(name)) { warning(wxT("Could not read name of NPC.")); return false; } } else if(creature_type == OTMM_MONSTER) { isNPC = false; if(!creatureNode->getString(name)) { warning(wxT("Could not read name of monster.")); return false; } if(!creatureNode->getU32(spawntime)) { warning(wxT("Could not read spawn time of monster.")); return false; } } else { warning(wxT("Unknown creature node type (0x%.2x)."), creature_type); return false; } // Read creature position uint16_t creature_x, creature_y; uint8_t creature_z; if(!creatureNode->getU16(creature_x) || !creatureNode->getU16(creature_y) || !creatureNode->getU8(creature_z) ) { warning(wxT("Could not read creature position.")); continue; } const Position creaturepos(creature_x, creature_y, creature_z); // Check radius if(uint32_t(abs(creaturepos.x - spawnpos.x)) > radius || uint32_t(abs(creaturepos.y - spawnpos.y)) > radius) { // Outside of the spawn... } // Create creature and put on map Tile* creature_tile; if(creaturepos == spawnpos) { creature_tile = spawn_tile; } else { creature_tile = map.getTile(creaturepos); } if(!creature_tile) { warning(wxT("Discarding creature \"%s\" at %d:%d:%d due to invalid position"), name.c_str(), creaturepos.x, creaturepos.y, creaturepos.z); break; } if(creature_tile->creature) { warning(wxT("Duplicate creature \"%s\" at %d:%d:%d, discarding"), name.c_str(), creaturepos.x, creaturepos.y, creaturepos.z); break; } CreatureType* type = creature_db[name]; if(!type) { type = creature_db.addMissingCreatureType(name, isNPC); } Creature* creature = newd Creature(type); creature->setSpawnTime(spawntime); creature_tile->creature = creature; if(creature_tile->spawn_count == 0) { // No spawn, create a newd one (this happends if the radius of the spawn has been decreased due to settings) ASSERT(creature_tile->spawn == NULL); Spawn* spawn = newd Spawn(5); creature_tile->spawn = spawn; map.addSpawn(creature_tile); } } while(creatureNode->advance()); } while(spawnNode->advance()); } break; case OTMM_TOWN_DATA: { BinaryNode* townNode = mapNode->getChild(); if(townNode) do { uint8_t town_type; if(!townNode->getByte(town_type)) { warning(wxT("Could not read town type")); continue; } if(town_type != OTMM_TOWN) { warning(wxT("Unknown town type")); continue; } uint32_t town_id; if(!townNode->getU32(town_id)) { warning(wxT("Invalid town id")); continue; } Town* town = map.towns.getTown(town_id); if(town) { warning(wxT("Duplicate town id %d, discarding duplicate"), town_id); continue; } else { town = newd Town(town_id); if(!map.towns.addTown(town)) { delete town; continue; } } std::string town_name; if(!townNode->getString(town_name)) { warning(wxT("Invalid town name")); continue; } town->setName(town_name); Position pos; uint16_t x; uint16_t y; uint8_t z; if(!townNode->getU16(x) || !townNode->getU16(y) || !townNode->getU8(z)) { warning(wxT("Invalid town temple position")); continue; } pos.x = x; pos.y = y; pos.z = z; town->setTemplePosition(pos); } while(townNode->advance()); } break; case OTMM_HOUSE_DATA: { BinaryNode* houseNode = mapNode->getChild(); if(houseNode) do { uint8_t house_type; if(!houseNode->getByte(house_type)) { warning(wxT("Could not read house type")); continue; } if(house_type != OTMM_HOUSE) { warning(wxT("Unknown house type.")); continue; } uint32_t house_id; if(!houseNode->getU32(house_id)) { warning(wxT("Could not read house id.")); continue; } House* house = map.houses.getHouse(house_id); if(!house) { continue; } std::string house_name; if(!houseNode->getString(house_name)) { warning(wxT("Could not read house name.")); continue; } uint32_t town_id; if(!houseNode->getU32(town_id)) { warning(wxT("Could not read house town id.")); continue; } uint32_t rent; if(!houseNode->getU32(rent)) { warning(wxT("Could not read house rent.")); continue; } house->name = house_name; house->townid = town_id; house->rent = rent; uint16_t x; uint16_t y; uint8_t z; if(!houseNode->getU16(x) || !houseNode->getU16(y) || !houseNode->getU8(z)) { warning(wxT("Invalid town temple position")); continue; } house->setExit(Position(x, y, z)); } while(houseNode->advance()); } break; } } while(mapNode->advance()); return true; }
bool _d2Run::Update(float Lag) { vector<item>::iterator inventoryIt; if(ticksDiff > 0.35f) { if( beltPotionsRejuve.size() < 8) { if( inventoryPotionsRejuve.size() > 0) { if( transferItem.Id == 0) { for(inventoryIt = inventoryPotionsRejuve.begin(); inventoryIt != inventoryPotionsRejuve.end(); inventoryIt++) { if(inventoryIt->pickupAttempted == false) { transferItem = *inventoryIt; inventoryIt->Id = 0; Core->itemToBelt( transferItem ); inventoryIt->pickupAttempted = true; ticksEnd = GetTickCount(); return true; } } // for } else { // transferItem.id == 0 transferCount++; if(transferCount > 10) { transferItem.Id = 0; ticksEnd = GetTickCount(); return true; } ticksEnd = GetTickCount(); return true; } } // inventoryPotions } } // ticksDiff >0.2 if(waitTimer && ticksDiff > 0.10f) { waitTimer--; ticksEnd = GetTickCount(); return true; } // 0 is right hand if(skillTargetID[0] != 0 || skillTargetID[1] != 0) { // Check our skills // Right Hand if(skillCurrentID[0] != skillTargetID[0]) { if(skillCounter[0]++ == 0) { Core->SkillSelect( skillTargetID[0], false); ticksEnd = GetTickCount(); } else { if(skillCounter[0] > 1000) { skillCounter[0] = 0; //Core->GameOver("Right Skill change failed!", true); } return true; } attackRecast = false; return true; } // skillCurrentID[0] // Left Hand if(skillCurrentID[1] != skillTargetID[1]) { if(skillCounter[1]++ == 0) { Core->SkillSelect( skillTargetID[1], true); ticksEnd = GetTickCount(); } else { if(skillCounter[1] > 1000) { skillCounter[1] = 0; //Core->GameOver("Left Skill change failed!", true); } return true; } attackRecast = false; return true; } //skillCurrentID[1] } // TargetIDs != 0 if(ticksDiff > 0.20f && pickItems.size() > 0 && pickTime && pickingItem.Id == 0) { if(pickupTele && !teleporting) pickupTele = false; if(!teleporting && !pickupTele) if(itemsPickup()) { ticksEnd = GetTickCount(); return true; } } if(groundItems.size() > 0 || pickingItem.Id) { item Item; if(pickupTele && !teleporting) pickupTele = false; if(ticksDiff > 0.20f && !teleporting && !pickupTele) { if(pickingItem.Id == 0) { for(size_t i = 0; i < groundItems.size(); i++) { // Need to clear this flag at the end of the monster waves if(groundItems[i].pickupAttempted) continue; strTmp.str(""); strTmp << "Picking Up "; if( !Item.Id ) if(groundItems[i].BaseItem == "rvl") { if(inventoryPotionsRejuve.size() < 5) { Item = groundItems[i]; strTmp << "Rejuvination Potion"; if(!Core->WithinRangePick( Item.Pos.xPos, Item.Pos.yPos ) ) { Item.Id = 0; teleSet( Item.Pos.xPos, Item.Pos.yPos, false ); pickupTele = true; return true; } } } if( !Item.Id && beltPotionsHealth.size() < 4) if(groundItems[i].BaseItem == "hp5") { Item = groundItems[i]; strTmp << "Health Potion"; if(!Core->WithinRangePick( Item.Pos.xPos, Item.Pos.yPos ) ) { Item.Id = 0; continue; } } if( !Item.Id && beltPotionsMana.size() < 4) if(groundItems[i].BaseItem == "mp5") { Item = groundItems[i]; strTmp << "Mana Potion"; if(!Core->WithinRangePick( Item.Pos.xPos, Item.Pos.yPos ) ) { Item.Id = 0; continue; } } if(Item.Id) { groundItems[i].pickupAttempted = true; pickedItem = false; pickingItem = Item; Core->pickItem( Item ); Core->Debug(2, strTmp.str()); ticksEnd = GetTickCount(); return true; } } // for } else { // pickingItem != 0 pickItemFailed++; ticksEnd = GetTickCount(); if(pickItemFailed > 5) { //if(groundItems.size()) //groundItemRemove(pickingItem.Id); pickingItem.Id = 0; return true; } return true; } } // ticksDiff > 0.20 if(pickingItem.Id != 0) return true; } // groundItems.size if(ticksDiff > 0.24f || walkComplete || (teleportFirstStep && !cta)) { if(followBots) { map<DWORD, _d2Player>::iterator Player; if(followMode == 0) { //if(publicMode) playersMuteAll(false); } // flowMode = 0 //if(followMode == 1) //Core->SpeakToAll("1"); if(followAllow) if(followMode == 2) Core->SpeakToAll("follow"); if(followMode == 3) Core->SpeakToAll("precast"); //if(followMode == 4) // Core->SpeakToAll("!bo"); // Check all bounds just incase if(followMode >= 4 || followMode < 0) { followMode = 0; followBots = false; } followMode++; ticksEnd = GetTickCount(); return true; } // followBots if(Running) { if(purchasing && purchaseComplete) { if(purchaseAmount--) { purchaseComplete = false; shoppingPurchasing = true; Core->TownPurchaseItem( unitMalah, purchaseItem, false ); ticksEnd = GetTickCount(); return true; } else { stepTown++; purchasing = false; shoppingPurchasing = false; ticksEnd = GetTickCount(); return true; } } else if (purchasing && !purchaseComplete) {// purchasing return true; } if(!town && cta) { CTARun(); ticksEnd = GetTickCount(); return true; } // !town && cta // CTAing before out of town if(town && cta) { if(currentStep == 0) { Core->GameOver("CTA in town!", false); return true; } else town = false; } if(portalCasting) { // Make it wait 3 seconds before rechucking if(!portalCast || ticksDiff > 4.0f) { portalCast = true; ThrowTP(); } //ticksEnd = GetTickCount(); return true; } // portalCasting } // Running if(interacting) { currentLevel = GetCurrentLevel(); if(currentLevel) if(currentLevel->dwLevelNo == LevelTarget) { Sleep(100); if(cMap.GenerateMap() == false) return true; Core->AllowPlayerReassign(); playerStop(); currentStep++; groundItems.clear(); LevelTarget = 0; interacting = false; interactingCount = 0; } else interactingCount++; if(interactingCount > 5) { Core->Debug(0, "Interaction failed"); interactingCount = 0; interacting = false; } free(currentLevel); ticksEnd = GetTickCount(); return true; } // Interacting if(Running && walking) { if(walkComplete) { walkComplete = false; if(walkStep == 0) { Core->playerMove( walkSteps[walkStep].X, walkSteps[walkStep].Y ); ticksEnd = GetTickCount(); return true; } } else { walkFailCounter++; if(walkFailCounter > 6) { walkFailCounter = 0; walkStep++; if(walkSteps[walkStep].X == 0) { walkComplete = false; walkStep--; Hero->posX = walkSteps[walkStep].X; Hero->posY = walkSteps[walkStep].Y; playerStop(); Core->playerMove(walkSteps[walkStep].X, walkSteps[walkStep].Y); walkCompleted(walkSteps[walkStep].X, walkSteps[walkStep].Y ); ticksEnd = GetTickCount(); return true; } } if(walkFailCounter == 0 || walkFailCounter == 5 || walkFailCounter == 10 || walkFailCounter == 15) Core->playerMove( walkSteps[walkStep].X, walkSteps[walkStep].Y ); walkComplete = false; ticksEnd = GetTickCount(); } return true; } // Running/Walking if(teleporting || teleportMoving) { if(ticksDiff > 0.30f || teleportFirstStep) { teleportFirstStep = false; if(teleStep >= teleSteps) { teleportTimeout++; if(( teleSteps > 1 && teleportTimeout > 150) || (teleportTimeout > 250)) { Core->Debug(0, "Teleport Timeout"); teleportTimeout = 0; teleStep = teleportCompleted + 1; teleFail++; if(telePath[ teleStep ].x == 0 || telePath[ teleStep ].y == 0) { teleStep--; if(teleStep < 0) teleStep = 0; } teleportMoving = true; if(teleFail > 3) { Core->Debug(0, "Teleport Failed"); teleporting = false; teleportMoving = false; teleportCompleted = 0; teleFail = 0; if(teleAbort) { gameTeleTimeout++; Core->GameOver("Teleporting Failed!", true); } return true; } return true; } else return true; } //telestep if(!teleportMoving) { teleportTimeout++; if(teleportTimeout > 300) { teleportTimeout = 0; //teleporting = false; teleportMoving = true; teleStep = teleportCompleted + 1; } return true; } if(telePath[ teleStep ].x == 0 || telePath[ teleStep ].y == 0) { //teleporting = false; teleportMoving = false; // This basically means we are waiting for us to arrive at our destination //teleSteps = 0; teleFail++; if(teleFail >= 3) { Core->Debug(0, "Teleport Failed"); teleporting = false; teleportMoving = false; teleportCompleted = 0; teleStep = 0; teleFail = 0; } return true; } Core->RightSkillFire( (WORD) telePath[ teleStep ].x, (WORD) telePath[ teleStep ].y ); teleStep++; ticksEnd = GetTickCount(); } // ticksdiff return true; } // teleporting if(ticksDiff > 0.30f) { if(town) { Running = true; Town(); ticksEnd = GetTickCount(); return true; } // Town } // ticksDiff (0.30) } float ticksDiffStart; ticksDiffStart = ((float) (ticksStartup - ticksEnd)) / 1000; if(ticksDiffStart > 10.0f) { if(firstLoad) { EnableDebugPriv(); if(!cMap.InitMemory("Diablo II", D2WindowTitle)) { //Quit = true; //Paused = true; //Core->Debug(0, "Init memory Failed!"); return true; } else { firstLoad = false; return true; } } currentLevel = GetCurrentLevel(); if(currentLevel) { if(currentLevel->dwLevelNo == 109) { // 109 = harrogath town = true; } else { if(town) firstTownLeave = true; town = false; } free(currentLevel); if(town && (currentStep > 0)) { if(realmCreateNewGame == true) return true; if(!manualMode) Core->GameOver("Found ourselves in town mid run!", true); Running = false; return true; } } } else // ticksdiffstart ticksEnd = GetTickCount(); return false; }