Beispiel #1
0
bool Character::enter(std::string dir) {
  Door* exit = location->getExit(dir);
  if (exit == NULL) {
    return false;
  } else {
    Room* newLocation = exit->getConnectedRoom(location);
    if (newLocation != NULL) {
      location->removeActor(this);
      location = newLocation;
      location->addActor(this);
      if (g->player->getLocation() == location) {
	addFlag("playerishere");
      } else if(checkFlag("playerishere")){
	removeFlag("playerishere");
      }
      triggerEnter(newLocation);
      return true;
    } else {
      g->push(exit->getLockedMessage());
      return true;
    }
  }
}
Beispiel #2
0
bool House::getAccessList(uint32_t listId, std::string& list) const
{
	if(listId == GUEST_LIST){
		guestList.getList(list);
		return true;
	}
	else if(listId == SUBOWNER_LIST){
		subOwnerList.getList(list);
		return true;
	}
	else{
		Door* door = getDoorByNumber(listId);
		if(door){
			return door->getAccessList(list);
		}
		else{
			#ifdef __DEBUG_HOUSES__
			std::cout << "Failure: [House::getAccessList] door == NULL, listId = " << listId <<std::endl;
			#endif
			return false;
		}
	}
	return false;
}
//doors
Door* TileMap::AddDoor(const char *ID, const char* Name, unsigned int Flags,
	int ClosedIndex, unsigned short* indices, int count,
	Gem_Polygon* open, Gem_Polygon* closed)
{
	Door* door = new Door( overlays[0] );
	door->Flags = Flags;
	door->closedIndex = ClosedIndex;
	door->SetTiles( indices, count );
	door->SetPolygon( false, closed );
	door->SetPolygon( true, open );
	door->SetName( ID );
	door->SetScriptName( Name );
	doors.push_back( door );
	return door;
}
Beispiel #4
0
Door* MazePrototypeFactory::MakeDoor(Room* r1, Room* r2) const{
    Door* door = m_pDoor->Clone();
    door->Initialize(r1, r2);
    return door;
}
Beispiel #5
0
//
// CastThroughIntersections
//
float Raycaster::CastThroughIntersections(float angle, IntersectionDir dir, int *texIndex, float *texelX)
{
	float fx, fy;
	float dx, dy;
	float distance;
	float a, b;
	int mapX, mapY;
	
	switch(dir)
	{
		case ID_HORIZONTAL:
			
			if(UP(angle))
			{
				fy = -(posY - (int)posY);
				dy = -1;
			}
			else
			{
				fy = (int)posY + 1 - posY;
				dy = 1;
			}
	
			fx = (float)(ABS(fy)) / (float)(TAN(angle));
			dx = (float)(ABS(dy)) / (float)(TAN(angle));
	
			fx = ABS(fx);
			dx = ABS(dx);
	
			if(LEFT(angle))
			{
				dx = -dx;
				fx = -fx;
			}
	
			fx = posX + fx;
			fy = posY + fy;
			
			break;
			
		case ID_VERTICAL:
			
			if(LEFT(angle))
			{		
				fx = -(posX - (int)posX);
				dx = -1;
			}
			else
			{
				fx = (int)posX + 1 - posX;
				dx = 1;
			}
	
			fy = (float)(TAN(angle)) * (float)(ABS(fx));
			dy = (float)(TAN(angle)) * (float)(ABS(dx));
	
			fy = ABS(fy);
			dy = ABS(dy);
	
			if(UP(angle))
			{
				fy = -fy;
				dy = -dy;
			}
	
			fx = posX + fx;
			fy = posY + fy;
			
			break;
	}
	
	while(true)
	{		
		mapY = (int)fy;
		mapX = (int)fx;
		
		if(dy == -1 && dir == ID_HORIZONTAL)
			mapY -= 1;
		else if(dx == -1 && dir == ID_VERTICAL)
			mapX -= 1;
		
		if(mapX < 0 || mapY < 0 || mapX >= mapW || mapY >= mapH)
			break;
		else if(map[mapY][mapX] > 0 && map[mapY][mapX] != DOOR_INDEX && map[mapY][mapX] != LOCKED_DOOR_INDEX)
		{
hit:
			if(dir == ID_HORIZONTAL)
				*texelX = fx - (float)mapX;
			else
				*texelX = fy - (float)mapY;
			
			*texIndex = map[mapY][mapX] - 1;
			break;
		}
		else if(map[mapY][mapX] == DOOR_INDEX || map[mapY][mapX] == LOCKED_DOOR_INDEX)
		{
			Door *door = GetDoorAt(mapX, mapY);
			
			if(door->GetOpening() || door->GetClosing())
			{
				float xval;
			
				if(dir == ID_HORIZONTAL)
					xval = fx - (float)mapX;
				else
					xval = fy - (float)mapY;
			
				if(door->GetOpenedWidth() < xval)			
					goto hit;
			}
			else if(!door->IsOpen())
				goto hit;
		}
		
		fx += dx;
		fy += dy;
	}
	
	a = ABS((fy - posY));
	b = ABS((fx - posX));
	
	distance = sqrt(a*a+b*b);
	
	return distance;
}
Beispiel #6
0
//
// OpenDoor
//
void Raycaster::OpenDoor(bool hasKey, bool *needAKey)
{
	static int doorPosX, doorPosY;
	static Uint32 lDoorOpen = 0;
	int i;
	
	// Don't close doors we're standing in
	if(map[(int)posY][(int)posX] == DOOR_INDEX)
		return;
		
	for(i=0; i<4; i++)
	{
		switch(i)
		{
			case 0:
				doorPosX = (int)posX;
				doorPosY = (int)posY + 1;
				break;
			case 1:
				doorPosX = (int)posX + 1;
				doorPosY = (int)posY;
				break;
			case 2:
				doorPosX = (int)posX;
				doorPosY = (int)posY - 1;
				break;
			case 3:
				doorPosX = (int)posX - 1;
				doorPosY = (int)posY;
				break;
		}
		
		if(doorPosX < 0 || doorPosY < 0)
			continue;
		
		if(map[doorPosY][doorPosX] == DOOR_INDEX || map[doorPosY][doorPosX] == LOCKED_DOOR_INDEX)
		{
			if(lDoorOpen == 0)
				lDoorOpen = SDL_GetTicks();
			else if(SDL_GetTicks() - lDoorOpen < DOOR_CHG_TIME)
				continue;
			
			Door *door = GetDoorAt(doorPosX, doorPosY);
			//door->SetOpen(!door->IsOpen());
			
			if(!door->IsLockedDoor() || hasKey)
			{			
				if(!door->IsOpen())
					door->SetOpening(true);
				else
					door->SetClosing(true);
				
				lDoorOpen = SDL_GetTicks();
			}
			else if(door->IsLockedDoor())
				*needAKey = true;
			
			return;
		}
		else if(map[doorPosY][doorPosX] == EXIT_DOOR_INDEX)
			mapChange = true;
	}
}
Beispiel #7
0
int main(int argc, char**argv)
{
  Arguments info;
  if(!parseOptions (argc, argv, info))
    return 1;

  ESMReader esm;
  esm.setEncoding(info.encoding);

  string filename = info.filename;
  cout << "\nFile: " << filename << endl;

  try {

  if(info.raw_given)
    {
      cout << "RAW file listing:\n";

      esm.openRaw(filename);

      printRaw(esm);

      return 0;
    }

  bool quiet = info.quiet_given;
  bool loadCells = info.loadcells_given;

  esm.open(filename);

  cout << "Author: " << esm.getAuthor() << endl;
  cout << "Description: " << esm.getDesc() << endl;
  cout << "File format version: " << esm.getFVer() << endl;
  cout << "Special flag: " << esm.getSpecial() << endl;
  cout << "Masters:\n";
  ESMReader::MasterList m = esm.getMasters();
  for(unsigned int i=0;i<m.size();i++)
    cout << "  " << m[i].name << ", " << m[i].size << " bytes\n";

  // Loop through all records
  while(esm.hasMoreRecs())
    {
      NAME n = esm.getRecName();
      esm.getRecHeader();
      string id = esm.getHNOString("NAME");
      if(!quiet)
        cout << "\nRecord: " << n.toString()
             << " '" << id << "'\n";

      switch(n.val)
        {
        case REC_ACTI:
          {
            Activator ac;
            ac.load(esm);
            if(quiet) break;
            cout << "  Name: " << ac.name << endl;
            cout << "  Mesh: " << ac.model << endl;
            cout << "  Script: " << ac.script << endl;
            break;
          }
        case REC_ALCH:
          {
            Potion p;
            p.load(esm);
            if(quiet) break;
            cout << "  Name: " << p.name << endl;
            break;
          }
        case REC_APPA:
          {
            Apparatus p;
            p.load(esm);
            if(quiet) break;
            cout << "  Name: " << p.name << endl;
            break;
          }
        case REC_ARMO:
          {
            Armor am;
            am.load(esm);
            if(quiet) break;
            cout << "  Name: " << am.name << endl;
            cout << "  Mesh: " << am.model << endl;
            cout << "  Icon: " << am.icon << endl;
            cout << "  Script: " << am.script << endl;
            cout << "  Enchantment: " << am.enchant << endl;
            cout << "  Type: " << am.data.type << endl;
            cout << "  Weight: " << am.data.weight << endl;
            break;
          }
        case REC_BODY:
          {
            BodyPart bp;
            bp.load(esm);
            if(quiet) break;
            cout << "  Name: " << bp.name << endl;
            cout << "  Mesh: " << bp.model << endl;
            break;
          }
        case REC_BOOK:
          {
            Book b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            cout << "  Mesh: " << b.model << endl;
            break;
          }
        case REC_BSGN:
          {
            BirthSign bs;
            bs.load(esm);
            if(quiet) break;
            cout << "  Name: " << bs.name << endl;
            cout << "  Texture: " << bs.texture << endl;
            cout << "  Description: " << bs.description << endl;
            break;
          }
        case REC_CELL:
          {
            Cell b;
            b.load(esm);
            if(!quiet)
              {
                cout << "  Name: " << b.name << endl;
                cout << "  Region: " << b.region << endl;
              }
            if(loadCells)
              loadCell(b, esm, quiet);
            break;
          }
        case REC_CLAS:
          {
            Class b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            cout << "  Description: " << b.description << endl;
            break;
          }
        case REC_CLOT:
          {
            Clothing b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_CONT:
          {
            Container b;
            b.load(esm);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_CREA:
          {
            Creature b;
            b.load(esm, id);
            if(quiet) break;
            cout << "  Name: " << b.name << endl;
            break;
          }
        case REC_DIAL:
          {
            Dialogue b;
            b.load(esm);
            break;
          }
        case REC_DOOR:
          {
            Door d;
            d.load(esm);
            if(quiet) break;
            cout << "  Name: " << d.name << endl;
            cout << "  Mesh: " << d.model << endl;
            cout << "  Script: " << d.script << endl;
            cout << "  OpenSound: " << d.openSound << endl;
            cout << "  CloseSound: " << d.closeSound << endl;
            break;
          }
        case REC_ENCH:
          {
            Enchantment b;
            b.load(esm);
            break;
          }
        case REC_GMST:
          {
            GameSetting b;
            b.id = id;
            b.load(esm);
            if(quiet) break;
            cout << "  Value: ";
            if(b.type == VT_String)
              cout << "'" << b.str << "' (string)";
            else if(b.type == VT_Float)
              cout << b.f << " (float)";
            else if(b.type == VT_Int)
              cout << b.i << " (int)";
            cout << "\n  Dirty: " << b.dirty << endl;
            break;
          }
        case REC_INFO:
          {
            DialInfo p;
            p.load(esm);
            if(quiet) break;
            cout << "  Id: " << p.id << endl;
            cout << "  Text: " << p.response << endl;
            break;
          }
        case REC_SOUN:
          {
            Sound d;
            d.load(esm);
            if(quiet) break;
            cout << "  Sound: " << d.sound << endl;
            cout << "  Volume: " << (int)d.data.volume << endl;
            break;
          }
        case REC_SPEL:
          {
            Spell s;
            s.load(esm);
            if(quiet) break;
            cout << "  Name: " << s.name << endl;
            break;
          }
        default:
          esm.skipRecord();
          if(quiet) break;
          cout << "  Skipping\n";
        }
    }

  } catch(exception &e)
    {
      cout << "\nERROR:\n\n  " << e.what() << endl;
      return 1;
    }

  return 0;
}
Beispiel #8
0
void Functions::actionOpenDoor(Aurora::NWScript::FunctionContext &ctx) {
	Door *door = Witcher::ObjectContainer::toDoor(getParamObject(ctx, 0));
	if (door)
		door->open(Witcher::ObjectContainer::toObject(ctx.getCaller()));
}
Beispiel #9
0
 static void activateFunc(size_t idx) { sDoors.activate(idx); }
Beispiel #10
0
Room *World::getRoom(const std::string &dungeon, int level)
{
	Room *room = 0;
	DungeonDescriptor dungDesc = worldDescriptor[dungeon];
	RoomDescriptor roomDesc = dungDesc.at(level);
	std::string parent = roomDesc["parent"];
	std::string music = roomDesc["music"];

	if (music != "")
		music = "music/" + music;

	if (roomDesc["method"] == "load")
	{
		room = RoomLoader::loadRoom("rooms/" + roomDesc["file"]);

		// Patch up the doors
		if (parent != "")
		{
			Door *d = room->findUnboundDoor(false);
			if (d)
			{
				d->setTargetDungeon(parent);
				d->setTargetLevel(0);
			}
		}
		
		if (level > 0)
		{
			Door *d = room->findUnboundDoor(false);
			if (d)
			{
				d->setTargetDungeon(dungeon);
				d->setTargetLevel(level - 1);
			}
		}

		if (level < (int)dungDesc.size() - 1)
		{
			Door *d = room->findUnboundDoor(true);
			if (d)
			{
				d->setTargetDungeon(dungeon);
				d->setTargetLevel(level + 1);
			}
		}
	}
	else if (roomDesc["method"] == "generate")
	{
		std::string tileSet = roomDesc["tileset"];
		std::string enemies = roomDesc["enemies"];
		int algorithm = fromString<int>(roomDesc["algorithm"]);
		int width = fromString<int>(roomDesc["width"]);
		int height = fromString<int>(roomDesc["height"]);
		int chests = fromString<int>(roomDesc["chests"]);

		int roomSeed = seed + level * 1000;
		for (int i = 0; i < (int)dungeon.size(); i++)
		{
			roomSeed = (roomSeed + 431) * dungeon[i];
		}
		
		Random random(roomSeed);

		room = RoomGenerator::generateRoom(width, height, (RoomGenerator::Algorithm)algorithm, "graphics/" + tileSet, enemies, chests, random);
		
		if (parent != "")
		{
			RoomGenerator::placeDoor(room, parent, 0, false, random);
		}
		
		if (level > 0)
		{
			RoomGenerator::placeDoor(room, dungeon, level - 1, false, random);
		}

		if (level < (int)dungDesc.size() - 1)
		{
			RoomGenerator::placeDoor(room, dungeon, level + 1, true, random);
		}
	}

	room->setDungeonName(dungeon);
	room->setDungeonLevel(level);
	room->setMusic(music);

	return room;
}
Beispiel #11
0
void DoorBrush::draw(BaseMap* map, Tile* tile, void* parameter) {
	for(ItemVector::iterator item_iter = tile->items.begin();
			item_iter != tile->items.end();)
	{
		Item* item = *item_iter;
		if(item->isWall() == false) {
			++item_iter;
			continue;
		}
		WallBrush* wb = item->getWallBrush();
		if(!wb) {
			++item_iter;
			continue;
		}

		BorderType wall_alignment = item->getWallAlignment();

		uint16_t discarded_id = 0; // The id of a discarded match
		bool close_match = false;
		bool perfect_match = false;

		bool open = false;
		if(parameter) {
			open = *reinterpret_cast<bool*>(parameter);
		}

		if(item->isBrushDoor()) {
			open = item->isOpen();
		}

		WallBrush* test_brush = wb;
		do {
			for(std::vector<WallBrush::DoorType>::iterator iter = test_brush->door_items[wall_alignment].begin();
					iter != test_brush->door_items[wall_alignment].end();
					++iter)
			{
				WallBrush::DoorType& dt = *iter;
				if(dt.type == doortype) {
					ASSERT(dt.id);
					ItemType& it = item_db[dt.id];
					ASSERT(it.id != 0);

					if(it.isOpen == open) {
						item = transformItem(item, dt.id, tile);
						perfect_match = true;
						break;
					} else if(close_match == false) {
						discarded_id = dt.id;
						close_match = true;
					}
					if(!close_match && discarded_id == 0) {
						discarded_id = dt.id;
					}
				}
			}
			test_brush = test_brush->redirect_to;
			if(perfect_match) {
				break;
			}
		} while(test_brush != wb && test_brush != nullptr);

		// If we've found no perfect match, use a close-to perfect
		if(perfect_match == false && discarded_id) {
			item = transformItem(item, discarded_id, tile);
		}

		if(settings.getInteger(Config::AUTO_ASSIGN_DOORID) && tile->isHouseTile()) {
			Map* mmap = dynamic_cast<Map*>(map);
			Door* door = dynamic_cast<Door*>(item);
			if(mmap && door) {
				House* house = mmap->houses.getHouse(tile->getHouseID());
				ASSERT(house);
				Map* real_map = dynamic_cast<Map*>(map);
				if(real_map) {
					door->setDoorID(house->getEmptyDoorID());
				}
			}
		}

		// We need to consider decorations!
		while(true) {
			// Vector has been modified, before we can use the iterator again we need to find the wall item again
			item_iter = tile->items.begin();
			while(true) {
				if(item_iter == tile->items.end()) {
					return;
				}
				if(*item_iter == item) {
					++item_iter;
					if(item_iter == tile->items.end()) {
						return;
					}
					break;
				}
				++item_iter;
			}
			// Now it points to the correct item!

			item = *item_iter;
			if(item->isWall()) {
				if(WallDecorationBrush* wdb = dynamic_cast<WallDecorationBrush*>(item->getWallBrush())) {
					// We got a decoration!
					for(std::vector<WallBrush::DoorType>::iterator iter = wdb->door_items[wall_alignment].begin();
							iter != wdb->door_items[wall_alignment].end();
							++iter)
					{
						WallBrush::DoorType& dt = *iter;
						if(dt.type == doortype) {
							ASSERT(dt.id);
							ItemType& it = item_db[dt.id];
							ASSERT(it.id != 0);

							if(it.isOpen == open) {
								item = transformItem(item, dt.id, tile);
								perfect_match = true;
								break;
							} else if(close_match == false) {
								discarded_id = dt.id;
								close_match = true;
							}
							if(!close_match && discarded_id == 0) {
								discarded_id = dt.id;
							}
						}
					}
					// If we've found no perfect match, use a close-to perfect
					if(perfect_match == false && discarded_id) {
						item = transformItem(item, discarded_id, tile);
					}
					continue;
				}
			}
			break;
		}
		// If we get this far in the loop we should return
		return;
	}
}
Beispiel #12
0
bool IOMapOTBM::loadMap(Map* map, const std::string& identifier)
{
	int64_t start = OTSYS_TIME();

	FileLoader f;
	if(!f.openFile(identifier.c_str(), false, true)){
    	std::stringstream ss;
		ss << "Could not open the file " << identifier << ".";
		setLastErrorString(ss.str());
		return false;
	}
	
	unsigned long type;
	PropStream propStream;

	NODE root = f.getChildNode((NODE)NULL, type);

	if(!f.getProps(root, propStream)){
		setLastErrorString("Could not read root property.");
		return false;
	}

	OTBM_root_header* root_header;
	if(!propStream.GET_STRUCT(root_header)){
		setLastErrorString("Could not read header.");
		return false;
	}
	
	if(root_header->version > 2){
		setLastErrorString("Unknown OTBM version detected, please update your server.");;
		return false;
	}
	
	if(root_header->majorVersionItems > (unsigned long)Items::dwMajorVersion){
		setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
		return false;
	}

	// Prevent load maps saved with items.otb previous to
	// version 800, because of the change to stackable of 
	// itemid 3965
	if(root_header->minorVersionItems < CLIENT_VERSION_760){
		setLastErrorString("This map needs to be updated.");
		return false;
	}

	if(root_header->minorVersionItems > (unsigned long)Items::dwMinorVersion){
		std::cout << "Warning: [OTBM loader] This map needs an updated items OTB file." <<std::endl;
	}

	std::cout << "Map size: " << root_header->width << "x" << root_header->height << std::endl;
	map->mapWidth = root_header->width;
	map->mapHeight = root_header->height;

	NODE nodeMap = f.getChildNode(root, type);
	
	if(type != OTBM_MAP_DATA){
		setLastErrorString("Could not read data node.");
		return false;
	}

	if(!f.getProps(nodeMap, propStream)){
		setLastErrorString("Could not read map data attributes.");
		return false;
	}

	unsigned char attribute;
	std::string mapDescription;
	std::string tmp;
	while(propStream.GET_UCHAR(attribute)){
		switch(attribute){
		case OTBM_ATTR_DESCRIPTION:
			if(!propStream.GET_STRING(mapDescription)){
				setLastErrorString("Invalid description tag.");
				return false;
			}
			
			std::cout << "Map description: " << mapDescription << std::endl;
			break;
		case OTBM_ATTR_EXT_SPAWN_FILE:
			if(!propStream.GET_STRING(tmp)){
				setLastErrorString("Invalid spawn tag.");
				return false;
			}

			map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1);
			map->spawnfile += tmp;

			break;
		case OTBM_ATTR_EXT_HOUSE_FILE:
			if(!propStream.GET_STRING(tmp)){
				setLastErrorString("Invalid house tag.");
				return false;
			}

			map->housefile = identifier.substr(0, identifier.rfind('/') + 1);
			map->housefile += tmp;
			break;

		default:
			setLastErrorString("Unknown header node.");
			return false;
			break;
		}
	}
	
	Tile* tile = NULL;

	NODE nodeMapData = f.getChildNode(nodeMap, type);
	while(nodeMapData != NO_NODE){
		if(f.getError() != ERROR_NONE){
			setLastErrorString("Invalid map node.");
			return false;
		}

		if(type == OTBM_TILE_AREA){
			if(!f.getProps(nodeMapData, propStream)){
				setLastErrorString("Invalid map node.");
				return false;
			}
			
			OTBM_Tile_area_coords* area_coord;
			if(!propStream.GET_STRUCT(area_coord)){
				setLastErrorString("Invalid map node.");
				return false;
			}
			
			int base_x, base_y, base_z;
			base_x = area_coord->_x;
			base_y = area_coord->_y;
			base_z = area_coord->_z;
			
			NODE nodeTile = f.getChildNode(nodeMapData, type);
			while(nodeTile != NO_NODE){
				if(f.getError() != ERROR_NONE){
					setLastErrorString("Could not read node data.");
					return false;
				}

				if(type == OTBM_TILE || type == OTBM_HOUSETILE){
					if(!f.getProps(nodeTile, propStream)){
						setLastErrorString("Could not read node data.");
						return false;
					}
					
					unsigned short px, py, pz;
					OTBM_Tile_coords* tile_coord;
					if(!propStream.GET_STRUCT(tile_coord)){
						setLastErrorString("Could not read tile position.");
						return false;
					}

					px = base_x + tile_coord->_x;
					py = base_y + tile_coord->_y;
					pz = base_z;
					
					bool isHouseTile = false;
					House* house = NULL;

					if(type == OTBM_TILE){
						tile = new Tile(px, py, pz);
					}
					else if(type == OTBM_HOUSETILE){
						uint32_t _houseid;
						if(!propStream.GET_ULONG(_houseid)){
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not read house id.";
							setLastErrorString(ss.str());
							return false;
						}

						house = Houses::getInstance().getHouse(_houseid, true);
						if(!house){
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not create house id: " << _houseid;
							setLastErrorString(ss.str());
							return false;
						}

						tile = new HouseTile(px, py, pz, house);
						house->addTile(static_cast<HouseTile*>(tile));
						isHouseTile = true;
					}

					//read tile attributes
					unsigned char attribute;
					while(propStream.GET_UCHAR(attribute)){
						switch(attribute){
						case OTBM_ATTR_TILE_FLAGS:
						{
							uint32_t flags;
							if(!propStream.GET_ULONG(flags)){
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to read tile flags.";
								setLastErrorString(ss.str());
								return false;
							}
								
							if((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE){
								tile->setFlag(TILESTATE_PROTECTIONZONE);
                            }
                            else if((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE){
                                tile->setFlag(TILESTATE_NOPVPZONE);
                            }
                            else if((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE){
                                tile->setFlag(TILESTATE_PVPZONE);
                            }
                            
                            if((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT){
                                tile->setFlag(TILESTATE_NOLOGOUT);
                            }

							if((flags & TILESTATE_REFRESH) == TILESTATE_REFRESH){
								if(house){
									std::cout << "Warning [x:" << px << ", y:" << py << ", z:" << pz << "] " << " House tile flagged as refreshing!";
								}
								tile->setFlag(TILESTATE_REFRESH);
							}
								
							break;
						}

						case OTBM_ATTR_ITEM:
						{
							Item* item = Item::CreateItem(propStream);
							if(!item){
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item.";
								setLastErrorString(ss.str());
								return false;
							}

							if(isHouseTile && !item->isNotMoveable()){
								std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getHouseId() << " Item type = " << item->getID() << std::endl;
								delete item;
								item = NULL;
							}
							else{
								tile->__internalAddThing(item);
								item->__startDecaying();
							}
							
							break;
						}

						default:
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown tile attribute.";
							setLastErrorString(ss.str());
							return false;
							break;
						}
					}

					NODE nodeItem = f.getChildNode(nodeTile, type);
					while(nodeItem){
						if(type == OTBM_ITEM){

							PropStream propStream;
							f.getProps(nodeItem, propStream);
							
							Item* item = Item::CreateItem(propStream);
							if(!item){
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item.";
								setLastErrorString(ss.str());
								return false;
							}

							if(item->unserializeItemNode(f, nodeItem, propStream)){
								if(isHouseTile && !item->isNotMoveable()){
									std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getHouseId() << " Item type = " << item->getID() << std::endl;
									delete item;
								}
								else{
									tile->__internalAddThing(item);
									item->__startDecaying();

									// TESTING
									if(isHouseTile){
										Door* door = item->getDoor();
										if(door && door->getDoorId() != 0){
											house->addDoor(door);
										}
									}
									//
								}
							}
							else{
                                std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to load item " << item->getID() << ".";
								setLastErrorString(ss.str());
								delete item;
								return false;
							}
						}
						else{
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown node type.";
							setLastErrorString(ss.str());
						}

						nodeItem = f.getNextNode(nodeItem, type);
					}
					
					map->setTile(px, py, pz, tile);
				}
				else{
					setLastErrorString("Unknown tile node.");
					return false;
				}

				nodeTile = f.getNextNode(nodeTile, type);
			}
		}
		else if(type == OTBM_TOWNS){
			NODE nodeTown = f.getChildNode(nodeMapData, type);
			while(nodeTown != NO_NODE){
				if(type == OTBM_TOWN){
					if(!f.getProps(nodeTown, propStream)){
						setLastErrorString("Could not read town data.");
						return false;
					}
					
					uint32_t townid = 0;
					if(!propStream.GET_ULONG(townid)){
						setLastErrorString("Could not read town id.");
						return false;
					}

					Town* town = Towns::getInstance().getTown(townid);
					if(!town){
						town = new Town(townid);
						Towns::getInstance().addTown(townid, town);
					}

					std::string townName = "";
					if(!propStream.GET_STRING(townName)){
						setLastErrorString("Could not read town name.");
						return false;
					}

					town->setName(townName);

					OTBM_TownTemple_coords *town_coords;
					if(!propStream.GET_STRUCT(town_coords)){
						setLastErrorString("Could not read town coordinates.");
						return false;
					}

					Position pos;
					pos.x = town_coords->_x;
					pos.y = town_coords->_y;
					pos.z = town_coords->_z;
					town->setTemplePos(pos);
				}
				else{
					setLastErrorString("Unknown town node.");
					return false;
				}

				nodeTown = f.getNextNode(nodeTown, type);
			}
		}
		else if(type == OTBM_WAYPOINTS && root_header->version >= 2){
			NODE nodeWaypoint = f.getChildNode(nodeMapData, type);
			while(nodeWaypoint != NO_NODE){
				if(type == OTBM_WAYPOINT){
					if(!f.getProps(nodeWaypoint, propStream)){
						setLastErrorString("Could not read town data.");
						return false;
					}

					std::string name;
					Position pos;

					if(!propStream.GET_STRING(name)){
						setLastErrorString("Could not read waypoint name.");
						return false;
					}

					OTBM_TownTemple_coords* wp_coords;
					if(!propStream.GET_STRUCT(wp_coords)){
						setLastErrorString("Could not read waypoint coordinates.");
						return false;
					}

					pos.x = wp_coords->_x;
					pos.y = wp_coords->_y;
					pos.z = wp_coords->_z;

					Waypoint_ptr wp(new Waypoint(name, pos));
					map->waypoints.addWaypoint(wp);
				}
				else{
					setLastErrorString("Unknown waypoint node.");
					return false;
				}

				nodeWaypoint = f.getNextNode(nodeWaypoint, type);
			}
		}
		else{
			setLastErrorString("Unknown map node.");
			return false;
		}

		nodeMapData = f.getNextNode(nodeMapData, type);
	}
	
	std::cout << "Notice: [OTBM Loader] Loading time : " << (OTSYS_TIME() - start)/(1000.) << " s" << std::endl;
	return true;
}
int main(int, char**) {


	//initialise SDL system and the video subsystem
	if (SDL_Init(SDL_INIT_VIDEO) != 0) {
		QuitWithError("SDL_Init Error: ");

	}

	//Create a Window
	SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (win == nullptr) {
		QuitWithError("SDL_CreateWindow Error: ");

	}

	//SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN);

	Mix_Music *music = NULL;
	Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 4096) == -1;
	std::string basepath(SDL_GetBasePath());
	music = Mix_LoadMUS((basepath + "background.wav").c_str());
	Mix_PlayMusic(music, -1);

	Render* renderer = new Render(win);

	//Main loop flag
	bool quit = false;
	b2Vec2 Gravity(0.f, 0.0098f);
	b2World World(Gravity);

	string bgPath = basepath + "background22.bmp";
	SDL_Surface* back = SDL_LoadBMP(bgPath.c_str());
	SDL_Rect* backGroundRect = renderer->AddSurfaceToRenderer(back, 0, -600, 1.0f);

	Button button = Button(-200, -50, World, renderer);
	Door door = Door(600, -100, renderer);

	Level level = Level(World, renderer);
	Player player = Player(100, 500, World, renderer);

	vector<Cannon*> cannons;
	cannons.push_back(new Cannon(170, 350, World, renderer, 1));
	cannons.push_back(new Cannon(1010, 50, World, renderer, 2));
	cannons.push_back(new Cannon(170, 450, World, renderer, 1));
	cannons.push_back(new Cannon(1010, 150, World, renderer, 2));
	cannons.push_back(new Cannon(170, 550, World, renderer, 1));
	cannons.push_back(new Cannon(1010, 250, World, renderer, 2));

	MenuScene* menu = new MenuScene(1200, 100, renderer);
	SDL_Event e;

	//thread t1(&Process::run, Process((*(game)))); //Passing references
	//t1.detach(); //detaches from SDL mainline

	float prevTicks = SDL_GetTicks();
	float currentTicks = SDL_GetTicks();
	float FPS = 0;

	int fpsTimer = 0;

	SDL_Init(0);

	//game loop
	while (!quit) {

		World.Step(1 / 60.f, 6, 2);
		while (SDL_PollEvent(&e) != 0) {
			if (inputHandler.CheckInput(SDLK_ESCAPE, e)) {
				quit = true;
			}
		}
		if (menu->playBool == false && menu->quitBool == false) {
			renderer->DrawMenuScene();
			menu->Update(renderer);
		}
		
		if (menu->playBool == true)
		{
			//PLAY GAME STATE
			int dir = player.Move(inputHandler, e);

			for (int i = 0; i < cannons.size(); i++)
			{
				cannons.at(i)->Update();
			}

			SDL_Rect rec(player.spriteRect);
			rec.y = player.GetY();

			for (int j = 0; j < cannons.size(); j++)
			{
				for (int i = 0; i < cannons.at(j)->fireballs.size(); i++)
				{
					if (cannons.at(j)->fireballs.at(i)->CheckCollision(&rec) == true)
					{
						std::cout << "Collision Detected!" << std::endl;
						player.Respawn();
						button.setOnce(false);
						button.buttonBody->SetTransform(b2Vec2(880 / SCALE, 39 / SCALE), 0);
						door.spriteRect->x = -1000;
						door.spriteRect->y = -1000;
						player.prevPosX.clear();
						player.prevPosY.clear();
						player.count = 0;
					}
				}
			}

			button.Update();
			
			if (button.CheckCollision(&rec) == true)
			{
				std::cout << "Collision Detected!" << std::endl;
				button.collision = true;
				button.spriteRect->x = -2000;
				button.spriteRect->y = -2000;
				button.buttonBody->SetTransform(b2Vec2(-2000, -2000), 0);
				//door.Draw(renderer);
			}
			if (door.CheckCollision(&rec) == true)
			{
				button.buttonBody->SetTransform(b2Vec2(880 / SCALE, 39/ SCALE), 0);
				std::cout << "Collision Detected!" << std::endl;
				player.Respawn();
				button.setOnce(false);
				door.spriteRect->x = -1000;
				door.spriteRect->y = -1000;
				player.prevPosX.clear();
				player.prevPosY.clear();
				player.count = 0;
				player.Respawn();
				menu->playBool = false;
				menu->quitBool = false;
				menu->backGroundRect->x = 0;
				menu->current = 0;
				button.collision = false;
			}
			if (button.collision == false)
			{
				door.DrawCage(renderer);
			}
			if (button.collision == true)
			{
				door.DrawNoCage(renderer);
			}

			int ticks = SDL_GetTicks();
			int seconds = ticks / 50;
			int sprite = seconds % 8;
			renderer->Update(player.srcRect, player.dstRect, *player.LeftTexture, *player.RightTexture, *player.StandTexture, sprite, dir, player.moving, player.GetY());
			player.dstRect.w = player.spriteRect.w;
			player.dstRect.h = player.spriteRect.h;
			player.dstRect.x = player.spriteRect.x;
			player.dstRect.y = player.spriteRect.y + 5;
		}

		if (menu->quitBool == true)
		{
			quit = true;
		}

		fpsthink();

		if (fpsTimer == 60)
		{
			printf("%f\n", framespersecond);
			fpsTimer = 0;
		}

		fpsTimer++;
	}
	SDL_DestroyRenderer(renderer->ren);
	SDL_DestroyWindow(win);
	SDL_DestroyMutex(mutex);

	SDL_Quit();
	return 0;
}
Beispiel #14
0
void Level::generate(GameState* state)
{
	// Create the starting room.
	rooms.push_back(new Room((m_width/2)-10, (m_height/2)-10, 10, 10, nullptr));
	
	// Add it to the list of rooms.
	Room* currentRoom = rooms.back();

	// Generate the room.
	currentRoom->fill(tiles);
	
	// Create other rooms.
	while( true )
	{
		// Get a direction to generate a new room in.
		Direction direction = currentRoom->getPossibleDirection();

		// Setup variables to generate doors and rooms.
		int doorAX, doorAY, roomX, roomY, roomW, roomH;
		
		// Get Width and Height of the room.
		roomW = 5 + rand() % 10;
		roomH = 5 + rand() % 10;
		
		// Depending on direction, roomX and roomY is altered, as with Doors.
		switch((int)direction)
		{
			case 0:
				doorAX = (currentRoom->getX()+1) + rand() % (currentRoom->getWidth()-2);
				doorAY = currentRoom->getY();
				
				roomX = doorAX - roomW/2;
				roomY = doorAY - roomH + 1;
			break;
				
			case 1:
				doorAX = (currentRoom->getX()+1) + rand() % (currentRoom->getWidth()-2);
				doorAY = currentRoom->getY()+currentRoom->getHeight()-1;
				
				roomX = doorAX - roomW/2;
				roomY = doorAY;
			break;
				
			case 2:
				doorAX = currentRoom->getX();
				doorAY = (currentRoom->getY()+1) + rand() % (currentRoom->getHeight()-2);
				
				roomX = doorAX - roomW + 1;
				roomY = doorAY - roomH/2;
			break;
				
			case 3:
				doorAX = currentRoom->getX()+currentRoom->getWidth()-1;
				doorAY = (currentRoom->getY()+1) + rand() % (currentRoom->getHeight()-2);
				
				roomX = doorAX;
				roomY = doorAY - roomH/2;
			break;
			
			default:
			break;
		}
		
		// Adjust coordinates accordingly, else room placement will freak out.
		if( roomY < 0 ) roomY = 0;
		if( roomX < 0 ) roomX = 0;
		if( roomX >= static_cast<int>(m_width) ) roomX = m_width - 1;
		if( roomY >= static_cast<int>(m_height) ) roomX = m_height - 1;
		
		// Make the new room.
		Room* newRoom = new Room(roomX, roomY, roomW, roomH, currentRoom);
		
		// Check if it's valid placement.
		if(newRoom->validPlacement(tiles, m_width, m_height))
		{
			// Fill the tiles with the room.
			newRoom->fill(tiles);
			fillAreaWithFog(newRoom);
			
			// Add the room to the vector.
			rooms.push_back(newRoom);
			
			// Remove the succeded Direction, because it's not available again.
			//currentRoom->removeDirection(direction);
			
			// Remove the opposite direction of current room.
			
			switch((int)direction)
			{
				case 0: newRoom->removeDirection(Direction::DOWN);  break;
				case 1: newRoom->removeDirection(Direction::UPP);   break;
				case 2: newRoom->removeDirection(Direction::RIGHT); break;
				case 3: newRoom->removeDirection(Direction::LEFT);  break;
			}
			
			// Set the current room to the new room.
			currentRoom = newRoom;
			
			// Alter the supposedly connected walls so a pathway is formed.
			Door* door = static_cast<Door*>( EntityFactory::get()->createEntity("door") );
			door->setX(doorAX*32);
			door->setY(doorAY*32);
			door->setConnectedRoom(currentRoom);
			door->setFogmap(&m_fogmap);
			
			tiles[doorAX][doorAY] = 1;
		}
		else
		{
			// Remove the room that failed.
			delete newRoom;

			// Remove the direction that failed
			currentRoom->removeDirection(direction);
			
			// If there are no more directions to go in the current room.
			if(currentRoom->possibleDirections() == 0)
			{
				// Move back one room and try to generate rooms in other directions
				Room* connectedRoom = currentRoom->getConnected();
				
				// If the connected room is start room then there is NO more to be done.
				if(connectedRoom == nullptr)
				{
					break;
				}
				
				// Set the current room to the room before.
				currentRoom = connectedRoom;
			}
		}
		
	}
	rooms[0]->showRoom(m_fogmap);
	
	int stairIndex = rand() % rooms.size();
	float stx = rooms[stairIndex]->getX() + rooms[stairIndex]->getWidth() / 2;
	float sty = rooms[stairIndex]->getY() + rooms[stairIndex]->getHeight()/ 2;
	
	Stairway* stairway = static_cast<Stairway*>(EntityFactory::get()->createEntity("stairway"));
	stairway->setX(stx*32);
	stairway->setY(sty*32);
	stairway->setGameState(state);
	
	std::ofstream ofs;
	ofs.open("level.txt");
	
	for( unsigned int y = 0; y < m_height; y++ )
	{
		for( unsigned int x = 0; x < m_width; x++ )
		{
			if( tiles[x][y] == 0)
				ofs << " ";
			else if ( tiles[x][y] == 2 || tiles[x][y] == 3 || tiles[x][y] == 4 )
				ofs << "W";
			else if ( tiles[x][y] == 5 )
				ofs << "D";
			else
				ofs << "#";
		}
		ofs << "\n";
	}
	ofs.close();
}
Beispiel #15
0
 static void deallocateFunc(size_t idx) { sDoors.deallocate(idx); }
// process all events that are specified in the level file
void Script::processEvents(const vector<World::scriptPos>& scripts){
  //vector<World::scriptPos>::iterator it = scripts.begin();
  //while (it != scripts.end()){
  for (unsigned i = 0; i < scripts.size(); i++){
    World::scriptPos sp = scripts[i];
    ScriptInfo* si = new ScriptInfo;
    //a trap?
    if (islower(sp.script[0])){
      if (sp.script[0] < 'n')
        lua_getglobal(L, "trapScheduler");
      else
        lua_getglobal(L, "eventScheduler");
      si->isTrap = true;
    }
    else{
      lua_getglobal(L, "eventScheduler");
      si->isTrap = false;
    }
    lua_pushstring(L, sp.script);
	  if (lua_pcall(L, 1, 1, 0) != 0){
		  cerr << lua_tostring(L, -1);
	  }
    string event = luaL_checkstring(L, -1);
    lua_pop(L, 1);

    si->pos = sp.pos;
    si->script[0] = sp.script[0];
    si->script[1] = sp.script[1];
    
    if (event == "OnInit"){
      lua_getglobal(L, sp.script);
	    lua_pushnumber(L, sp.pos.x);
	    lua_pushnumber(L, sp.pos.y);
	    if (lua_pcall(L, 2, 0, 0) != 0){
		    cerr << lua_tostring(L, -1);
	    }  
    }
    else if (event == "OnTreasure"){
      si->event = OnTreasure;
      scripts_.push_back(si);
      Field& f = wrld.getField(si->pos);
      f.script = scripts_.back();
    }
    else if (event == "OnWalkAt"){
      si->event = OnWalkAt;
      scripts_.push_back(si);
      Field& f = wrld.getField(si->pos);
      f.script = scripts_.back(); 
    }
    else if (event == "OnOpen"){
      si->event = OnOpen;
      scripts_.push_back(si);
      Door* d = wrld.getDoor(si->pos, TOP);
      if (d)
        d->setScript(scripts_.back());
      d = wrld.getDoor(si->pos, RIGHT);
      if (d)
        d->setScript(scripts_.back());
      d = wrld.getDoor(si->pos, BOTTOM);
      if (d)
        d->setScript(scripts_.back());
      d = wrld.getDoor(si->pos, LEFT);
      if (d)
        d->setScript(scripts_.back());
    }
    else{
      cerr << "Unknown script event: "+event;
    }
    
    //TODO
    /*
    lua_getglobal(L, sp.script);
	  lua_pushnumber(L, sp.pos.x);
	  lua_pushnumber(L, sp.pos.y);
	  if (lua_pcall(L, 2, 0, 0) != 0){
		  cerr << lua_tostring(L, -1);
	  }
    */
    //it++;
  }
}
Beispiel #17
0
bool DoorsDataUser::CheckCollision(PVRTVec3 nodeWorldPos, float walkDistance)
{
    JoyStick * pJoyStick = JoyStick::GetJoyStick();
    
	PVRTVec2 vecLeft = pJoyStick->GetVectorLeft();
	PVRTVec2 vecRight = pJoyStick->GetVectorRight();

	vecLeft.normalize();
	vecLeft.y*=-1.0f;

	PVRTVec2 nodeNewPos(nodeWorldPos.x, nodeWorldPos.z);
	PVRTVec2 globalTan(0.0f,0.0f);

	int collisionCount = 0;

	for (int p=0;p<mNumDoorsData;p++)
	{
		DoorsData * pDoorsData = mDoorsData[p];
		int numOfDoors = pDoorsData->GetNumOfDoors();
		for (int d=0;d<numOfDoors;d++)
		{
			Door * pDoor = pDoorsData->GetDoor(d);
			if (pDoor->GetState() == Door::door_state_open)
				continue;

			int numOfDoorEdges = pDoor->GetNumOfDoorEdges();
			for (int e = 0 ; e< numOfDoorEdges ; e++)
			{
				DoorEdge * edge = pDoor->GetDoorEdge(e);
				Line2D line;
				line.p0.x = edge->x1;
				line.p0.y = edge->z1;

				line.p1.x = edge->x2;
				line.p1.y = edge->z2;
				
				float dist = Collision::Vec2DistanceFromLine2D(line, nodeNewPos);
				if (dist < MM(walkDistance))
				{								
					PVRTVec2 wall(edge->nx, edge->nz);
					globalTan+=wall.normalized();
					collisionCount++;
				}
			}
												
		}
	}

	if (collisionCount > 0)
	{
		globalTan/=(float)collisionCount;

		float deltaAngle = acos(vecLeft.dot(globalTan));
		if (  deltaAngle >= PVRT_PI*0.5f )
		{
			return true;
		}
	}

	return false;
}
Beispiel #18
0
bool
Script::_EvaluateTrigger(trigger_node* trig)
{
	Actor* actor = dynamic_cast<Actor*>(fTarget.Target());
	if (actor != NULL && actor->SkipConditions())
		return false;

#if DEBUG_SCRIPTS
	printf("SCRIPT: %s%s (%d 0x%x) ? ",
			trig->flags != 0 ? "!" : "",
			IDTable::TriggerAt(trig->id).c_str(),
			trig->id, trig->id);
	trig->Print();
#endif

	Core* core = Core::Get();
	bool returnValue = false;
	try {
		switch (trig->id) {
			case 0x0002:
			{
				/* 0x0002 AttackedBy(O:Object*,I:Style*AStyles)
				 * Returns true only if the active CRE was attacked in the style
				 * specified (not necessarily hit) or had an offensive spell cast
				 * on it by the specified object in the last script round.
				 * The style parameter is non functional - this trigger is triggered
				 * by any attack style.
				 */
				object_node* node = FindObjectNode(trig);
				if (node == NULL)
					break;
				node->Print();
				ScriptResults* results = fTarget.Target()->LastScriptRoundResults();
				if (results != NULL) {
					Object* object = Object::GetMatchingObjectFromList(
							results->Attackers(), node);

					returnValue = object != NULL;
				}
				break;
			}
			case 0x400A:
			{
				//ALIGNMENT(O:OBJECT*,I:ALIGNMENT*Align) (16395 0x400A)
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsAlignment(trig->parameter1);

				break;
			}
			case 0x400B:
			{
				//ALLEGIANCE(O:OBJECT*,I:ALLEGIENCE*EA) (16395 0x400b)
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsEnemyAlly(trig->parameter1);

				break;
			}
			case 0x400C:
			{
				/*0x400C Class(O:Object*,I:Class*Class)*/
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsClass(trig->parameter1);
				break;
			}
			case 0x400E:
			{
				/* GENERAL(O:OBJECT*,I:GENERAL*GENERAL) (16398 0x400e)*/
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsGeneral(trig->parameter1);
				break;
			}
			case 0x400F:
			{
				/*0x400F Global(S:Name*,S:Area*,I:Value*)
				Returns true only if the variable with name 1st parameter
				of type 2nd parameter has value 3rd parameter.*/
				std::string variableScope;
				variableScope.append(trig->string1, 6);
				std::string variableName;
				variableName.append(&trig->string1[6]);

				int32 variableValue = 0;
				if (variableScope.compare("LOCALS") == 0) {
					variableValue = fTarget.Target()->GetVariable(variableName.c_str());
				} else {
					// TODO: Check for AREA variables, currently we
					// treat AREA variables as global variables
					variableValue = Core::Get()->GetVariable(variableName.c_str());
				}
				returnValue = variableValue == trig->parameter1;
				break;
			}
			case 0x0020:
			{
				// HitBy
				// Returns true on first Script launch, IOW initial area load
				if (!Processed()) {
					returnValue = true;
					break;
				}
				//object_node* object = FindObjectNode(trig);
				//returnValue = Object::CheckIfNodeInList(object,
				//		fTarget->LastScriptRoundResults()->Hitters());
				break;
			}
			case 0x0022:
			{
				/* TimerExpired(I:ID*) */
				std::ostringstream stringStream;
				stringStream << fTarget.Target()->Name() << " " << trig->parameter1;
				printf("TimerExpired %s\n", stringStream.str().c_str());
				GameTimer* timer = GameTimer::Get(stringStream.str().c_str());
				if (timer != NULL && timer->Expired()) {
					returnValue = true;
				}
				break;
			}
			case 0x002F:
			{
				/* 0x002F Heard(O:Object*,I:ID*SHOUTIDS)
				Returns true only if the active CRE was within 30 feet
				of the specified object and the specified object shouted
				the specified number (which does not have to be in
				SHOUTIDS.ids) in the last script round.
				NB. If the object is specified as a death variable,
				the trigger will only return true if the corresponding
				object shouting also has an Enemy-Ally flag of NEUTRAL. */
				Object* object = FindObject(trig);
				if (object != NULL && core->Distance(fTarget.Target(), object) <= 30
						&& object->LastScriptRoundResults()->Shouted()
						== trig->parameter1) {
					returnValue = true;
				}
				break;
			}


			case 0x4017:
			{
				// Race()
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsRace(trig->parameter1);

				break;
			}

			case 0x4018:
			{
				/* 0x4018 Range(O:Object*,I:Range*)
				Returns true only if the specified object
				is within distance given (in feet) of the active CRE. */
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = core->Distance(object, fTarget.Target()) <= trig->parameter1;
				break;
			}

			case 0x401C:
			{
				/* See(O:Object*)
				 * Returns true only if the active CRE can see
				 * the specified object which must not be hidden or invisible.
				 */
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = core->See(fTarget.Target(), object);
				break;
			}
			case 0x401E:
			{
				/* Time(I:Time*Time)
				 * Returns true only if the period of day matches the period
				 * in the 2nd parameter (taken from Time.ids).
				 * Hours are offset by 30 minutes, e.g. Time(1) is true
				 * between 00:30 and 01:29.
				 */
				break;
			}

			case 0x4023:
				/* 0x4023 True() */
				returnValue = true;
				break;
			case 0x4027:
			{
				//DELAY(I:DELAY*) (16423 0x4027)
				// TODO: Implement
				returnValue = true;
				break;
			}
			case 0x402b:
			{
				/* ACTIONLISTEMPTY() (16427 0x402b)*/
				returnValue = fTarget.Target()->IsActionListEmpty();
				break;
			}
			case 0x4034:
			{
				/*0x4034 GlobalGT(S:Name*,S:Area*,I:Value*)
				See Global(S:Name*,S:Area*,I:Value*) except the variable
				must be greater than the value specified to be true.
				*/
				returnValue = core->GetVariable(trig->string1) > trig->parameter1;
				break;
			}
			case 0x4035:
			{	/*
				0x4035 GlobalLT(S:Name*,S:Area*,I:Value*)
				As above except for less than. */
				returnValue = core->GetVariable(trig->string1) < trig->parameter1;
				break;
			}
			case 0x0036:
			{
				/*0x0036 OnCreation()
				Returns true if the script is processed for the first time this session,
				e.g. when a creature is created (for CRE scripts) or when the player
				enters an area (for ARE scripts).*/
				returnValue = !Processed();
				break;
			}
			case 0x4037:
			{
				/* StateCheck(O:Object*,I:State*State)
				 * Returns true only if the specified object
				 * is in the state specified.
				 */
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = object->IsState(trig->parameter1);
				break;
			}
			case 0x4039:
			{
				/* NUMBEROFTIMESTALKEDTO(I:NUM*) (16441 0x4039) */
				if (actor->NumTimesTalkedTo() == (uint32)trig->parameter1)
					returnValue = true;
				break;
			}
			case 0x4040:
			{
				/* GlobalTimerExpired(S:Name*,S:Area*) (16448 0x4040) */
				// TODO: Merge Name and Area before passing them to the
				// Timer::Get() method (also below)
				std::string timerName;
				timerName.append(trig->string2).append(trig->string1);
				GameTimer* timer = GameTimer::Get(timerName.c_str());
				returnValue = timer != NULL && timer->Expired();
				break;
			}
			case 0x4041:
			{
				/* GlobalTimerNotExpired(S:Name*,S:Area*) */
				std::string timerName;
				timerName.append(trig->string2).append(trig->string1);
				GameTimer* timer = GameTimer::Get(timerName.c_str());
				returnValue = timer == NULL || !timer->Expired();
				break;
			}
			case 0x4043:
			{
				// InParty
				const Actor* actor = dynamic_cast<const Actor*>(FindObject(trig));
				if (actor != NULL)
					returnValue = Game::Get()->Party()->HasActor(actor);

				break;
			}
			case 0x4051:
			{
				/*
				 * 0x4051 Dead(S:Name*)
				 * Returns only true if the creature with the specified script name
				 * has its death variable set to 1. Not every form of death sets this,
				 * but most do. So it's an almost complete test for death.
				 * The creature must have existed for this to be true.
				 * Note that SPRITE_IS_DEAD variables are not set if the creature is
				 * killed by a neutral creature.
				 */
				/*Script* actorScript = fScripts[trig->string1];
				if (actorScript != NULL) {
					// TODO: More NULL checking
					const char* deathVariable = actorScript->Target()->CRE()->DeathVariable();
					returnValue = fVariables[deathVariable] == 1;
				}*/
				break;
			}
			case 0x52:
			{
				/* OPENED(O:OBJECT*) (82 0x52) */
				object_node* objectNode = FindObjectNode(trig);
				if (objectNode == NULL)
					break;
				// TODO: We assume this is a door, but also
				// containers can be opened/closed
				Door* door = dynamic_cast<Door*>(fTarget.Target());
				if (door == NULL)
					break;
				if (!door->Opened())
					break;

				Object* object = core->GetObject(
						door->CurrentScriptRoundResults()->fOpenedBy.c_str());
				if (object != NULL)
					returnValue = object->MatchNode(objectNode);

				break;
			}
			case 0x4063:
			{
				/*INWEAPONRANGE(O:OBJECT*) (16483 0x4063) */
				int range = 40;
				// TODO: Check weapon range
				Object* object = FindObject(trig);
				if (object != NULL)
					returnValue = core->Distance(object, fTarget.Target()) <= range;

				break;
			}

#if 0
			case 0x4068:
			{
				/* TimeGT(I:Time*Time)
				 * Returns true only if the current time is greater than
				 * that specified. Hours are offset by 30 minutes,
				 * e.g. TimeGT(1) is true between 01:30 and 02:29.
				 */
				break;
			}

			case 0x4069:
			{
				//TIMELT(I:TIME*TIME) (16489 0x4069)
				break;
			}
#endif
			case 0x0070:
			{
				/* 0x0070 Clicked(O:Object*)
				 *	Only for trigger regions.
				 *	Returns true if the specified object
				 *	clicked on the trigger region running this script.
				 */
				object_node* objectNode = FindObjectNode(trig);
				returnValue = fTarget.Target()->LastScriptRoundResults()->Clicker()
						->MatchNode(objectNode);
				//objectNode->Print();
				fTarget.Target()->LastScriptRoundResults()->Clicker()->Print();

				// TODO: When to set this, other than now ?
				if (returnValue)
					fLastTrigger = fTarget;
				break;
			}

			case 0x4074:
			{
				/*
				 * 0x4074 Detect(O:Object*)
				 * Returns true if the the specified object
				 * is detected by the active CRE in any way
				 * (hearing or sight). Neither Move Silently
				 * and Hide in Shadows prevent creatures
				 * being detected via Detect().
				 * Detect ignores Protection from Creature
				 * type effects for static objects.
				 */
				Object* object = core->GetObject(fTarget.Target(), FindObjectNode(trig));
				if (object != NULL)
					returnValue = core->See(fTarget.Target(), object);
					// || core->Hear(fTarget, object);
				break;
			}

			case 0x4076:
			{
				/*
				 * 0x4076 OpenState(O:Object*,I:Open*BOOLEAN)
				 * NT Returns true only if the open state of the specified door
				 * matches the state specified in the 2nd parameter.
				 */
				object_node* doorObj = FindObjectNode(trig);
				Door *door = dynamic_cast<Door*>(
								core->GetObject(doorObj->name));
				if (door != NULL) {
					bool openState = trig->parameter1 == 1;
					returnValue = door->Opened() == openState;
				}
				break;
			}
			case 0x407D:
			{
				/* ISOVERME(O:Object*)
				 * Only for trigger regions. Returns true only if the specified
				 * object is over the trigger running the script
				 */
				object_node* object = FindObjectNode(trig);
				if (object != NULL) {
					Object* objectOverRegion = core->GetObject(
							dynamic_cast<Region*>(fTarget.Target()));
					if (objectOverRegion != NULL)
						returnValue = objectOverRegion->MatchNode(object);
				}

				break;
			}
			case 0x407E:
			{
				/* 0x407E AreaCheck(S:ResRef*)
				 * Returns true only if the active CRE
				 * is in the area specified.
				 */
				// TODO: We only check the active area
				returnValue = !strcmp(RoomContainer::Get()->Name(), trig->string1);
				break;
			}
			case 0x4086:
			{
				// AREATYPE(I:NUMBER*AREATYPE) (16518 0x4086)

				// TODO: We only check the active area
				const uint16 areaType = RoomContainer::Get()->AREA()->Type();
				returnValue = areaType & trig->parameter1;
				break;
			}
			case 0x4089:
			{
				/*0x4089 OR(I:OrCount*)*/
				fOrTriggers = trig->parameter1;
				returnValue = true;
				break;
			}
			case 0x401b:
			{
				/* REPUTATIONLT(O:OBJECT*,I:REPUTATION*) (16411 0x401b) */
				Actor* actor = dynamic_cast<Actor*>(FindObject(trig));
				if (actor != NULL) {
					returnValue = actor->CRE()->Reputation() < trig->parameter1;
				}
				break;
			}

			case 0x4c:
			{
				// Entered(O:Object)
				object_node* node = FindObjectNode(trig);
				Region* region = dynamic_cast<Region*>(fTarget.Target());
				//std::vector<std::string>::const_iterator i;
				Object* object = Object::GetMatchingObjectFromList(
										region->
										LastScriptRoundResults()->
										EnteredActors(), node);
				if (object != NULL) {
					fLastTrigger = object;
					returnValue = true;
				}
				break;
			}
			default:
			{
				printf("SCRIPT: UNIMPLEMENTED TRIGGER!!!\n");
				printf("SCRIPT: %s (%d 0x%x)\n", IDTable::TriggerAt(trig->id).c_str(),
								trig->id, trig->id);
				trig->Print();
				break;
			}
		}
	} catch (...) {
		printf("SCRIPT: EvaluateTrigger() caught exception");
	}
	if (trig->flags != 0)
		returnValue = !returnValue;
#if DEBUG_SCRIPTS
	printf("SCRIPT: (%s)\n", returnValue ? "TRUE" : "FALSE");
#endif
	return returnValue;
}
Beispiel #19
0
void Functions::actionCloseDoor(Aurora::NWScript::FunctionContext &ctx) {
	Door *door = NWN::ObjectContainer::toDoor(getParamObject(ctx, 0));
	if (door)
		door->close(NWN::ObjectContainer::toObject(ctx.getCaller()));
}
void Player::update(float deltaTime){

	getRigidBody()->activate();

	// modifying the speed based on the movement mode
	if (inputHandler.isKeyDown(KEY_LCONTROL)){
		// stealth movement
		_mod = 2.0f;
	}
	else
		// normal movement
		_mod = 5.0f;

	if (inputHandler.isKeyDown(KEY_LSHIFT))
		_mod *= 2.0f;

	//make noise unless crouched, more when sprinting
	if (inputHandler.isKeyDown(KEY_LSHIFT) && (inputHandler.isKeyDown(KEY_KEY_W) || inputHandler.isKeyDown(KEY_KEY_A) || inputHandler.isKeyDown(KEY_KEY_S) || inputHandler.isKeyDown(KEY_KEY_D))){
		_noiseAllowance -= 0.020f;
	}
	else if (!inputHandler.isKeyDown(KEY_LCONTROL) && (inputHandler.isKeyDown(KEY_KEY_W) || inputHandler.isKeyDown(KEY_KEY_A) || inputHandler.isKeyDown(KEY_KEY_S) || inputHandler.isKeyDown(KEY_KEY_D))){
		_noiseAllowance -= 0.005f;
	}


	/* SETTING UP THE DIRECTION MATRIX */

	// preparing the matrix
	matrix4 mat0;
	mat0.setRotationAxisRadians(_yaw, vector3df(0, 1, 0));

	matrix4 mat1;
	mat1.setRotationAxisRadians(_pitch, vector3df(1, 0, 0));

	matrix4 mat = IdentityMatrix;
	mat = mat0 * mat1;

	// transform direction vectors based on the orientation of the player
	vector3df backward(0.0f, 0.0f, -1.0f);
	vector3df toLeft(-1.0f, 0.0f, .0f);
	vector3df toRight(1.0f, 0.0f, 0.0f);
	vector3df forward(0.0f, 0.0f, 1.0f);
	vector3df up(0.0f, 1.0f, 0.0f);

	mat.transformVect(forward);
	mat.transformVect(backward);
	mat.transformVect(toLeft);
	mat.transformVect(toRight);

	setForward(forward);
	setUp(up);

	/* MOVEMENT */

	// setting key press events
	if (inputHandler.isKeyDown(KEY_KEY_D) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(toRight.X, 0.0f, -toRight.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_A) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(toLeft.X, 0.0f, -toLeft.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_S) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-backward.X, 0.0f, backward.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_W) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-forward.X, 0.0f, forward.Z)*_mod);
	}
	// setting double key press events
	if (inputHandler.isKeyDown(KEY_KEY_W) && inputHandler.isKeyDown(KEY_KEY_A) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-forward.X + toLeft.X, 0.0f, forward.Z - toLeft.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_W) && inputHandler.isKeyDown(KEY_KEY_D) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-forward.X + toRight.X, 0.0f, forward.Z - toRight.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_S) && inputHandler.isKeyDown(KEY_KEY_A) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-backward.X + toLeft.X, 0.0f, backward.Z - toLeft.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_KEY_S) && inputHandler.isKeyDown(KEY_KEY_D) && isDown()) {
		this->getRigidBody()->setLinearVelocity(btVector3(-backward.X + toRight.X, 0.0f, backward.Z - toRight.Z)*_mod);
	}

	// jump!
	if (inputHandler.isKeyDown(KEY_SPACE) && !inputHandler.wasKeyDown(KEY_SPACE) && isDown() && !isStealthActive()) {
		getRigidBody()->setLinearVelocity(btVector3(up.X, up.Y*_mod, up.Z));
		game.getAudioEngine()->play2D("sounds/common/jump.wav");
		_noiseAllowance -= 2.0f;
	}
	// TODO: fix the jumping and moving forward feature
	if (inputHandler.isKeyDown(KEY_SPACE) && inputHandler.isKeyDown(KEY_KEY_W) && isDown() && !isStealthActive()) {
		getRigidBody()->setLinearVelocity(btVector3(up.X - forward.X, up.Y, up.Z + forward.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_SPACE) && inputHandler.isKeyDown(KEY_KEY_S) && isDown() && !isStealthActive()) {
		getRigidBody()->setLinearVelocity(btVector3(up.X - backward.X, up.Y, up.Z + backward.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_SPACE) && inputHandler.isKeyDown(KEY_KEY_A) && isDown() && !isStealthActive()) {
		getRigidBody()->setLinearVelocity(btVector3(up.X + toLeft.X, up.Y, up.Z - toLeft.Z)*_mod);
	}
	if (inputHandler.isKeyDown(KEY_SPACE) && inputHandler.isKeyDown(KEY_KEY_D) && isDown() && !isStealthActive()) {
		getRigidBody()->setLinearVelocity(btVector3(up.X + toRight.X, up.Y, up.Z - toRight.Z)*_mod);
	}

	/* THROWABLE OBJECTS*/

	//action key
	if (inputHandler.isKeyDown(KEY_KEY_E) && !inputHandler.wasKeyDown(KEY_KEY_E)){
		if (_isCarrying){//dropping
			if (this->getCarriedItem() != NULL){
				this->_isCarrying = false;
				Message m(this->getCarriedItem(), "dropped", 0);
				MessageHandler::sendMessage(m);
				this->clearCarriedItem();
				_hasKey = false;
				_noiseAllowance -= 1.0f;
			}
		}
		else{//picking up
			std::list<Entity*>* objects = EntityManager::getNamedEntities("Object");
			vector3df playerPos = _node->getPosition();
			auto iter = objects->begin();
			while (iter != objects->end()){
				Object* obj = (Object*)(*iter);
				btVector3 hm = obj->getRigidBody()->getCenterOfMassPosition();
				vector3df objPos = vector3df(hm.getX(), hm.getY(), hm.getZ());
				vector3df toPlayer = playerPos - objPos;
				if (toPlayer.getLength() < 5 && (getCurrentRoom() == obj->getCurrentRoom())){
					if (obj->getItemName() == "key") {
						_hasKey = true;
						std::cout << _hasKey << std::endl;
					}					
					obj->setPickedUp(true);
					this->setCarriedItem(obj);
					this->_isCarrying = true;
					//does the player need a hint?
					HudManager* hud = (HudManager*)EntityManager::getNamedEntities("Hudman")->front();
					if (!hud->hasHintBeenShownFor("Throw")){
						hud->drawHintFor("Throw");
					}
					break;
				}
				iter++;
			}

		}
	}

	if (inputHandler.getCurrentMouse().LeftButton){
		if (_isCarrying){//dropping
			if (this->getCarriedItem() != NULL){
				this->_isCarrying = false;
				Message m(this->getCarriedItem(), "thrown", 0);
				MessageHandler::sendMessage(m);
				this->clearCarriedItem();
				_noiseAllowance -= 5.0f;
				//does the player need a hint?
				HudManager* hud = (HudManager*)EntityManager::getNamedEntities("Hudman")->front();
				if (!hud->hasHintBeenShownFor("Noise")){
					hud->drawHintFor("Noise");
				}
				_hasKey = false;
			}
		}
	}

	/* CHECKING THE DOORS */
	std::list<Entity*>* doors = EntityManager::getNamedEntities("Door");
	vector3df playerPos = _node->getPosition();
	auto doorIter = doors->begin();
	while (doorIter != doors->end()){

		Door* door = (Door*)(*doorIter);
		btVector3 btPos = door->getRigidBody()->getCenterOfMassPosition();
		vector3df doorPos = vector3df(btPos.x(), btPos.y(), btPos.z());
		vector3df toPlayer = playerPos - doorPos;

		if (toPlayer.getLength() < 3 && inputHandler.isKeyDown(KEY_KEY_F) && !inputHandler.wasKeyDown(KEY_KEY_F)) {
			btTransform transform = getRigidBody()->getCenterOfMassTransform();

			if (door->getDirection() == 1 && playerPos.X < doorPos.X && !door->isExit()) {
				transform.setOrigin(btVector3(doorPos.X + 2.0f, playerPos.Y, doorPos.Z));
			}
			else if (door->getDirection() == 2 && playerPos.X > doorPos.X && !door->isExit()) {
				transform.setOrigin(btVector3(doorPos.X - 2.0f, playerPos.Y, doorPos.Z));
			}
			else if (door->getDirection() == 3 && playerPos.Z < doorPos.Z && !door->isExit()) {
				transform.setOrigin(btVector3(doorPos.X, playerPos.Y, doorPos.Z + 2.0f));
			}
			else if (door->getDirection() == 4 && playerPos.Z > doorPos.Z && !door->isExit()) {
				transform.setOrigin(btVector3(doorPos.X, playerPos.Y, doorPos.Z - 2.0f));
			}
			else if (door->getDirection() == 2 && playerPos.X > doorPos.X && door->isExit() && _hasKey) {
				//exitdoor with key
				game.setEndCause((allItemsCollected() ? "win" : "fail"));
				game.setNoiseMade(_startingNoise - _noiseAllowance);
				inputHandler.setEnded(true);
			}
			else if (door->getDirection() == 2 && playerPos.X > doorPos.X && door->isExit() && !_hasKey){
				game.getAudioEngine()->play2D("sounds/common/locked_door.wav");
			}

			getRigidBody()->setCenterOfMassTransform(transform);
		}
		doorIter++;
	}
	/* GET THE ROOM THE PLAYER IS IN */
	std::list<Entity*>* rooms = EntityManager::getNamedEntities("Room");
	playerPos = _node->getPosition();
	auto iterator = rooms->begin();
	while (iterator != rooms->end()){

		Room* room = (Room*)(*iterator);
		vector3df roomPos = room->getPosition();
		vector3df roomScale = room->getScale();
		vector3df toPlayer = playerPos - roomPos;
		if (toPlayer.getLength() < roomScale.Z / 2)
			setCurrentRoom(room->getName());
		iterator++;
	}

	if (_noiseAllowance<0.0f){
		game.setEndCause("lose");
		inputHandler.setEnded(true);
	}
}
void CAIVolume::Init(int32 iVolume, const AIVolume& vol)
{
	char szName[128];
    g_pLTServer->GetObjectName(vol.m_hObject, szName, 127);
    m_hstrName = g_pLTServer->CreateString(szName);

	m_iVolume = iVolume;

    LTVector vVolumePos;
    LTVector vVolumeDims;

    g_pLTServer->GetObjectPos(vol.m_hObject, &vVolumePos);
    g_pLTServer->GetObjectDims(vol.m_hObject, &vVolumeDims);

    m_vFrontTopRight    = vVolumePos + LTVector(vVolumeDims.x,   vVolumeDims.y,  vVolumeDims.z);
    m_vFrontTopLeft     = vVolumePos + LTVector(-vVolumeDims.x,  vVolumeDims.y,  vVolumeDims.z);
    m_vBackTopRight     = vVolumePos + LTVector(vVolumeDims.x,   vVolumeDims.y,  -vVolumeDims.z);
    m_vBackTopLeft      = vVolumePos + LTVector(-vVolumeDims.x,  vVolumeDims.y,  -vVolumeDims.z);
    m_vFrontBottomRight = vVolumePos + LTVector(vVolumeDims.x,   -vVolumeDims.y, vVolumeDims.z);
    m_vFrontBottomLeft  = vVolumePos + LTVector(-vVolumeDims.x,  -vVolumeDims.y, vVolumeDims.z);
    m_vBackBottomRight  = vVolumePos + LTVector(vVolumeDims.x,   -vVolumeDims.y, -vVolumeDims.z);
    m_vBackBottomLeft   = vVolumePos + LTVector(-vVolumeDims.x,  -vVolumeDims.y, -vVolumeDims.z);

	// Get the view volumes

	for ( uint32 iViewNode = 0 ; iViewNode < kMaxViewNodes ; iViewNode++ )
	{
		if ( vol.GetViewNode(iViewNode) )
		{
			CAINode* pNode = g_pAINodeMgr->GetNode(vol.GetViewNode(iViewNode));

			if ( pNode )
			{
				m_adwViewNodes[iViewNode] = pNode->GetID();
			}
			else
			{
				g_pLTServer->CPrint("********** Volume ''%s'' has a view node that does not exist!", GetName());
			}
		}
	}

	// Find any doors located in our volume

    HCLASS  hDoor = g_pLTServer->GetClass("Door");
    HCLASS  hSwitch = g_pLTServer->GetClass("Switch");
    HOBJECT hCurObject = LTNULL;
    while (hCurObject = g_pLTServer->GetNextObject(hCurObject))
	{
        if (g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hDoor) && !g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hSwitch))
		{
            Door* pDoor = (Door*)g_pLTServer->HandleToObject(hCurObject);
			if ( !pDoor->IsAITriggerable() ) continue;

            LTVector vPos;
            LTVector vDims;

            g_pLTServer->GetObjectPos(hCurObject, &vPos);
            g_pLTServer->GetObjectDims(hCurObject, &vDims);

			if ( Inside(vPos, vDims.y*2.0f) )
			{
				if ( m_cDoors == cm_nMaxDoors )
				{
					_ASSERT(!"Max number of doors in a volume exceeded!!!!");
                    g_pLTServer->CPrint("Max number of doors in a volume exceeded!!!!");
				}
				else
				{
                    m_bHadDoors = LTTRUE;
					g_pAIVolumeMgr->Link(hCurObject);
					m_ahDoors[m_cDoors++] = hCurObject;
				}
			}
		}
	}

    hCurObject = LTNULL;
    while (hCurObject = g_pLTServer->GetNextInactiveObject(hCurObject))
	{
        if (g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hDoor) && !g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hSwitch))
		{
            Door* pDoor = (Door*)g_pLTServer->HandleToObject(hCurObject);
			if ( !pDoor->IsAITriggerable() ) continue;

            LTVector vPos;
            LTVector vDims;

            g_pLTServer->GetObjectPos(hCurObject, &vPos);
            g_pLTServer->GetObjectDims(hCurObject, &vDims);

			if ( Inside(vPos, vDims.y*2.0f) )
			{
				if ( m_cDoors == cm_nMaxDoors )
				{
					_ASSERT(!"Max number of doors in a volume exceeded!!!!");
                    g_pLTServer->CPrint("Max number of doors in a volume exceeded!!!!");
				}
				else
				{
                    m_bHadDoors = LTTRUE;
					g_pAIVolumeMgr->Link(hCurObject);
					m_ahDoors[m_cDoors++] = hCurObject;
				}
			}
		}
	}

	// Validate volume dims. Must be 64x64 if there's no doors. One side must be <= 128 if there are doors
#ifndef _FINAL // Don't spam multiplayer server with warnings...
	if ( m_cDoors == 0 )
	{
		if ( vVolumeDims.x < 32 )
            g_pLTServer->CPrint("WARNING: Volume \"%s\" is only %d units wide/x (should be at least 64)", GetName(), (int)vVolumeDims.x*2);

		if ( vVolumeDims.z < 32 )
            g_pLTServer->CPrint("WARNING: Volume \"%s\" is only %d units deep/z (should be at least 64)", GetName(), (int)vVolumeDims.z*2);
	}
	else //	if ( m_cDoors != 0 )
	{
		if ( vVolumeDims.x >= 128 && vVolumeDims.z >= 128 )
            g_pLTServer->CPrint("WARNING: Volume \"%s\" is a suspiciously large door volume!", GetName());
	}
#endif

	// Misc flags that have been set

	m_bStairs = vol.HasStairs();
	m_vStairsDir = vol.GetStairsDir();

	m_bLedge = vol.HasLedge();
	m_vLedgeDir = vol.GetLedgeDir();

	m_bVertical = vol.IsVertical();
}