void SetLinkEventMask(int room, std::string index, std::string maskdef) 
	{ 
		int i;

		// c=click, u=up, d=down, e=enter, l=leave, m=move
		unsigned int mask = 0;
		for (i=0; i<maskdef.length(); ++i) {
			switch(maskdef[i]) {
			case 'c': case 'C': mask |= BaseInterface::Room::Link::ClickEvent; break;
			case 'u': case 'U': mask |= BaseInterface::Room::Link::UpEvent; break;
			case 'd': case 'D': mask |= BaseInterface::Room::Link::DownEvent; break;
			case 'e': case 'E': mask |= BaseInterface::Room::Link::EnterEvent; break;
			case 'l': case 'L': mask |= BaseInterface::Room::Link::LeaveEvent; break;
			case 'm': case 'M':
				fprintf(stderr,"%s: WARNING: Ignoring request for movement event mask.\n", __FILE__);
				//mask |= BaseInterface::Room::Link::MoveEvent;
				break;
			}
		} 

		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (i=0; i<newroom->links.size();i++) {
			if (newroom->links[i]) {
				if (newroom->links[i]->index==index) {
					// FIXME: Will crash if not a Goto object.
					newroom->links[i]->setEventMask(mask);
				}
			}
		}
	}
	void LinkPython (int room, std::string index,std::string pythonfile, float x, float y, float wid, float hei, std::string text, int to) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		newroom->links.push_back(new BaseInterface::Room::Goto (index,pythonfile));
		BaseLink(newroom,x,y,wid,hei,text);
		((BaseInterface::Room::Goto*)newroom->links.back())->index=to;
	}
	void Ship (int room, std::string index,QVector pos,Vector Q, Vector R) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		Vector P = R.Cross(Q);
		P.Normalize();
		newroom->objs.push_back(new BaseInterface::Room::BaseShip(P.i,P.j,P.k,Q.i,Q.j,Q.k,R.i,R.j,R.k,pos,index));
//		return BaseInterface::CurrentBase->rooms[BaseInterface::CurrentBase->curroom]->links.size()-1;
	}
 void Video(int room, std::string index, std::string vfile, std::string afile, float x, float y) {
     BaseInterface::Room *newroom=CheckRoom(room);
     if (!newroom) return;
     
     BaseUtil::Texture(room, index, vfile, x, y);
     
     int sndstream = AUDCreateMusic(afile);
     dynamic_cast<BaseInterface::Room::BaseVSSprite*>(newroom->objs.back())->spr.SetTimeSource(sndstream);
 }
	void SetLinkPython(int room, std::string index, std::string python)
	{
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->links.size();i++) {
			if (newroom->links[i]) {
				if (newroom->links[i]->index==index) {
					newroom->links[i]->Relink(python);
				}
			}
		}
	}
	void SetLinkText(int room, std::string index, std::string text)
	{
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->links.size();i++) {
			if (newroom->links[i]) {
				if (newroom->links[i]->index==index) {
					newroom->links[i]->text= text;
				}
			}
		}
	}
	void SetTextBoxText(int room, std::string index, std::string text) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->objs.size();i++) {
			if (newroom->objs[i]) {
				if (newroom->objs[i]->index==index) {
					// FIXME: Will crash if not a Text object.
					dynamic_cast<BaseInterface::Room::BaseText*>(newroom->objs[i])->SetText(text);
				}
			}
		}
	}
	void Python(int room, std::string index, float x, float y, float wid, float hei, std::string text, std::string pythonfile,bool front) {
		//instead of "Talk"/"Say" tags
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		BaseInterface::Room::Python * tmp = new BaseInterface::Room::Python (index,pythonfile);
		if (front) {
			newroom->links.insert(newroom->links.begin(),tmp);
		} else {
			newroom->links.push_back(tmp);
		}
		BaseLink(newroom,x,y,wid,hei,text,front);
	}
	void SetLinkRoom(int room, std::string index, int to)
	{
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->links.size();i++) {
			if (newroom->links[i]) {
				if (newroom->links[i]->index==index) {
					// FIXME: Will crash if not a Goto object.
					dynamic_cast<BaseInterface::Room::Goto*>(newroom->links[i])->index = to;
				}
			}
		}
	}
	void SetTextureSize(int room, std::string index, float w, float h)
	{
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->objs.size();i++) {
			if (newroom->objs[i]) {
				if (newroom->objs[i]->index==index) {
					// FIXME: Will crash if not a Sprite object.
					dynamic_cast<BaseInterface::Room::BaseVSSprite*>(newroom->objs[i])->SetSize(w,h);
				}
			}
		}
	}
	void EraseObj (int room, std::string index) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<(int)newroom->objs.size();i++) {
			if (newroom->objs[i]) {
				if (newroom->objs[i]->index==index) {
					newroom->objs.erase(newroom->objs.begin()+i);
                                        i--;
//					break;
				}
			}
		}
	}
void BossBloodPrinceValanarAI::UpdateAI(const uint32 diff)
{
    if (!UpdateVictim() || !CheckRoom())
        return;

    events.Update(diff);

    if (me->HasUnitState(UNIT_STATE_CASTING))
        return;

    while (uint32 eventId = events.ExecuteEvent())
    {
        switch (eventId)
        {
            case EVENT_BERSERK:
                DoCast(me, SPELL_BERSERK);
                Talk(SAY_VALANAR_BERSERK);
                break;
            case EVENT_KINETIC_BOMB:
                if (instance->GetData(DATA_KINETIC_BOMB_COUNT) < RAID_MODE<uint32>(2, 3, 2, 3))
                {
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
                    {
                        DoCast(target, SPELL_KINETIC_BOMB_TARGET);
                        Talk(SAY_VALANAR_SPECIAL);
                    }
                    instance->SetData(DATA_KINETIC_BOMB_COUNT, instance->GetData(DATA_KINETIC_BOMB_COUNT) + 1);
                }
                events.ScheduleEvent(EVENT_KINETIC_BOMB, urand(18000, 24000));
                break;
            case EVENT_SHOCK_VORTEX:
                if (_isEmpowered)
                {
                    DoCast(me, SPELL_EMPOWERED_SHOCK_VORTEX);
                    Talk(EMOTE_VALANAR_SHOCK_VORTEX);
                    events.ScheduleEvent(EVENT_SHOCK_VORTEX, 30000);
                }
                else
                {
                    if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
                        DoCast(target, SPELL_SHOCK_VORTEX);
                    events.ScheduleEvent(EVENT_SHOCK_VORTEX, urand(18000, 23000));
                }
                break;
            default:
                break;
        }
    }

    DoMeleeAttackIfReady();
}
	void Texture(int room, std::string index, std::string file, float x, float y) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		newroom->objs.push_back(new BaseInterface::Room::BaseVSSprite(file.c_str(),index));
#ifdef BASE_MAKER
		((BaseInterface::Room::BaseVSSprite*)newroom->objs.back())->texfile=file;
#endif
		float tx=0, ty=0;
		static bool addspritepos = XMLSupport::parse_bool(vs_config->getVariable("graphics","offset_sprites_by_pos","true"));
		if (addspritepos)
			((BaseInterface::Room::BaseVSSprite*)newroom->objs.back())->spr.GetPosition(tx,ty);
                
		dynamic_cast<BaseInterface::Room::BaseVSSprite*>(newroom->objs.back())->spr.SetPosition(x+tx,y+ty);
	}
	void SetLinkArea(int room, std::string index, float x, float y, float wid, float hei)
	{
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		for (int i=0;i<newroom->links.size();i++) {
			if (newroom->links[i]) {
				if (newroom->links[i]->index==index) {
					newroom->links[i]->x   = x;
					newroom->links[i]->y   = y;
					newroom->links[i]->wid = wid;
					newroom->links[i]->hei = hei;
				}
			}
		}
	}
 void PlayVideo(int room, std::string index)
 {
     BaseInterface::Room *newroom=CheckRoom(room);
     if (!newroom) return;
     for (int i=0;i<newroom->objs.size();i++) {
         if (newroom->objs[i]) {
             if (newroom->objs[i]->index==index) {
                 // FIXME: Will crash if not a Sprite object.
                 int snd = dynamic_cast<BaseInterface::Room::BaseVSSprite*>(newroom->objs[i])->spr.GetTimeSource();
                 if (snd)
                     AUDStartPlaying(snd);
             }
         }
     }
 }
    void VideoStream(int room, std::string index, std::string streamfile, float x, float y, float w, float h) {
        BaseInterface::Room *newroom=CheckRoom(room);
        if (!newroom) return;
        
        static bool addspritepos = XMLSupport::parse_bool(vs_config->getVariable("graphics","offset_sprites_by_pos","true"));
        float tx=0, ty=0;
        
        BaseInterface::Room::BaseVSSprite *newobj = new BaseInterface::Room::BaseVSMovie(streamfile, index);
        if (addspritepos)
            newobj->spr.GetPosition(tx,ty);
        newobj->spr.SetPosition(x+tx,y+ty);
        newobj->spr.SetSize(w,h);
        
#ifdef BASE_MAKER
        newobj->texfile=file;
#endif
        
        newroom->objs.push_back(newobj);
    }
	void CompPython(int room, std::string index,std::string pythonfile, float x, float y, float wid, float hei, std::string text, std::string modes) { 
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		BaseInterface::Room::Comp *newcomp=new BaseInterface::Room::Comp (index,pythonfile);
		newroom->links.push_back(newcomp);
		BaseLink(newroom,x,y,wid,hei,text);
		static const EnumMap::Pair modelist [] = {
			EnumMap::Pair ("Cargo", BaseComputer::CARGO), 
			EnumMap::Pair ("Upgrade", BaseComputer::UPGRADE), 
			EnumMap::Pair ("ShipDealer", BaseComputer::SHIP_DEALER), 
			EnumMap::Pair ("Missions", BaseComputer::MISSIONS),
			EnumMap::Pair ("News", BaseComputer::NEWS), 
			EnumMap::Pair ("Info", BaseComputer::INFO),
			EnumMap::Pair ("LoadSave", BaseComputer::LOADSAVE), 
			EnumMap::Pair ("Network", BaseComputer::NETWORK),
			EnumMap::Pair ("UNKNOWN", BaseComputer::LOADSAVE),
		};
		static const EnumMap modemap (modelist,sizeof(modelist)/sizeof(*modelist));
		const char *newmode=modes.c_str();
		int newlen=modes.size();
		char *curmode=new char [newlen+1];
		for (int i=0;i<newlen;) {
			int j;
			for (j=0;newmode[i]!=' '&&newmode[i]!='\0';i++,j++) {
				curmode[j]=newmode[i];
			}
			while(newmode[i]==' ')
				i++;
			if (j==0)
				continue;
			//in otherwords, if j is 0 then the 0th index will become null
			//EnumMap crashes if the string is empty.
			curmode[j]='\0';
			int modearg = modemap.lookup(curmode);
			if (modearg<BaseComputer::DISPLAY_MODE_COUNT) {
				newcomp->modes.push_back((BaseComputer::DisplayMode)(modearg));
			} else {
				VSFileSystem::vs_fprintf(stderr,"WARNING: Unknown computer mode %s found in python script...\n",curmode);
			}
		}
		delete [] curmode;
	}
	void RunScript (int room, std::string ind, std::string pythonfile, float time) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		newroom->objs.push_back(new BaseInterface::Room::BasePython(ind, pythonfile, time));
	}
	void SetCurRoom (int room) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		if (!BaseInterface::CurrentBase) return;
		BaseInterface::CurrentBase->GotoLink(room);
	}
	void TextBox (int room, std::string ind, std::string text, float x, float y, Vector widheimult, Vector backcol, float backalp, Vector forecol) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		newroom->objs.push_back(new BaseInterface::Room::BaseText(text, x, y, widheimult.i, widheimult.j, widheimult.k, GFXColor(backcol, backalp), GFXColor(forecol), ind));
	}
	void EjectPython (int room, std::string index,std::string pythonfile, float x, float y, float wid, float hei, std::string text) {
		BaseInterface::Room *newroom=CheckRoom(room);
		if (!newroom) return;
		newroom->links.push_back(new BaseInterface::Room::Eject (index,pythonfile));
		BaseLink(newroom,x,y,wid,hei,text);
	}