Пример #1
0
bool
Script::_ExecuteAction(action_node* act)
{
#if DEBUG_SCRIPTS
	printf("SCRIPT: %s (%d 0x%x)\n", IDTable::ActionAt(act->id).c_str(), act->id, act->id);
	act->Print();
#endif
	Core* core = Core::Get();
	Actor* thisActor = dynamic_cast<Actor*>(fTarget.Target());

	switch (act->id) {
		case 0x03:
		{
			/* Attack(O:Target*) */
			Object* targetObject = FindObject(act);
			if (targetObject != NULL) {
				Actor* targetActor = dynamic_cast<Actor*>(targetObject);
				if (thisActor != NULL && targetActor != NULL) {
					Attack* attackAction = new Attack(thisActor, targetActor);
					thisActor->AddAction(attackAction);
				}
			}
			break;
		}
		case 0x07:
		{
			/* CreateCreature(S:NewObject*,P:Location*,I:Face*) */
			// TODO: If point is (-1, -1) we should put the actor near
			// the active creature. Which one is the active creature?
			IE::point point = act->where;
			if (point.x == -1 && point.y == -1) {
				point = Game::Get()->Party()->ActorAt(0)->Position();
				point.x += Core::RandomNumber(-20, 20);
				point.y += Core::RandomNumber(-20, 20);
			}

			Actor* actor = new Actor(act->string1, point, act->integer1);
			RoomContainer::Get()->ActorEnteredArea(actor);

			// TODO: Add actor to the current area
			break;
		}

		case 0x8:
		{
			/*	DIALOGUE(O:OBJECT*) (8 0x8) */
			Actor* actor = dynamic_cast<Actor*>(FindObject(act));
			if (actor != NULL) {
				Dialogue* dialogueAction = new Dialogue(thisActor, actor);
				thisActor->AddAction(dialogueAction);
			}
			break;
		}
		case 0xA:
		{
			/* ENEMY() (10 0xa) */
			uint32 id = IDTable::EnemyAllyValue("ENEM");
			thisActor->SetEnemyAlly(id);
			break;
		}
		case 22:
		{
			// MoveToObject
			Object* object = FindObject(act);
			if (object != NULL) {
				WalkTo* walkTo = new WalkTo(thisActor, object->Position());
				fTarget.Target()->AddAction(walkTo);
			}

			break;
		}
		case 23:
		{
			// MoveToPoint
			Actor* actor = dynamic_cast<Actor*>(fTarget.Target());
			if (actor != NULL) {
				WalkTo* walkTo = new WalkTo(actor, act->where);
				actor->AddAction(walkTo);
				actor->StopCheckingConditions();
			}
			break;
		}
		case 29:
		{
			/* RunAwayFrom(O:Creature*,I:Time*) */
			Actor* targetActor = dynamic_cast<Actor*>(FindObject(act));
			if (targetActor != NULL && thisActor != NULL) {
				RunAwayFrom* run = new RunAwayFrom(thisActor, targetActor);
				fTarget.Target()->AddAction(run);
			}
			break;
		}
		case 36:
		{
			/*
			 * 36 Continue()
			 * This action instructs the script parser to continue looking
			 * for actions in the active creatures action list.
			 * This is mainly included in scripts for efficiency.
			 * Continue should also be appended to any script blocks added
			 * to the top of existing scripts, to ensure correct functioning
			 * of any blocks which include the OnCreation trigger.
			 * Continue may prevent actions being completed until the script
			 * parser has finished its execution cycle. Continue() must be
			 * the last command in an action list to function correctly.
			 * Use of continue in a script block will cause the parser
			 * to treater subsequent empty response blocks as though they
			 * contained a Continue() command - this parsing can be stopped
			 * by including a NoAction() in the empty response block.
			 */
			// TODO: Implement
			break;
		}
		case 61:
		{
			/* 61 StartTimer(I:ID*,I:Time*)
			This action starts a timer local to the active creature.
			The timer is measured in seconds, and the timer value is
			not saved in save games. The timer is checked with the
			TimerExpired trigger.*/

			// TODO: We should add the timer local to the active creature,
			// whatever that means
			if (fTarget.Target() == NULL)
				printf("NULL TARGET\n");
			std::ostringstream stringStream;
			stringStream << fTarget.Target()->Name() << " " << act->integer1;

			GameTimer::Add(stringStream.str().c_str(), act->integer2);

			break;
		}
		case 85:
		{
			/* 85 RandomWalk */
			if (thisActor != NULL && thisActor->IsInterruptable())
				core->RandomWalk(thisActor);
			break;
		}
		case 86:
		{
			/* 86 SetInterrupt(I:State*Boolean) */
			if (thisActor != NULL)
				thisActor->SetInterruptable(act->integer1 == 1);
			break;
		}
		case 0x1E:
		{
			std::string variableScope;
			variableScope.append(act->string1, 6);
			std::string variableName;
			variableName.append(&act->string1[6]);

			if (variableScope.compare("LOCALS") == 0) {
				if (fTarget != NULL)
					fTarget.Target()->SetVariable(variableName.c_str(),
							act->integer1);
			} else {
				// TODO: Check for AREA variables
				core->SetVariable(variableName.c_str(),
						act->integer1);
			}
			break;
		}
		case 0x53:
		{
			/* 83 SmallWait(I:Time*) */
			// TODO: The time is probably wrong
			Wait* wait = new Wait(thisActor, act->integer1);
			fTarget.Target()->AddAction(wait);
			break;
		}

		case 106:
		{
			/* Shout */
			// Check if target is silenced
			if (thisActor != NULL)
				thisActor->Shout(act->integer1);
			break;
		}
		case 0x64:
		{
			/* 100 RandomFly */
			if (thisActor != NULL && thisActor->IsInterruptable())
				core->RandomFly(thisActor);
			break;
		}
		case 0x65:
		{
			/* 101 FlyToPoint(Point, Time) */
			if (thisActor != NULL && thisActor->IsInterruptable()) {
				FlyTo* flyTo = new FlyTo(thisActor, act->where, act->integer1);
				thisActor->AddAction(flyTo);
			}
			break;
		}
		case 111:
		{
			/* DESTROYSELF() (111 0x6f) */
			// TODO: Delete it for real
			fTarget.Target()->SetStale(true);
			return false;
		}
		case 0x73:
		{
			/* SETGLOBALTIMER(S:NAME*,S:AREA*,I:TIME*GTIMES) (115 0x73)*/
			std::string timerName;
			// TODO: We append the timer name to the area name,
			// check if it's okay
			timerName.append(act->string2).append(act->string1);
			GameTimer::Add(timerName.c_str(), act->integer1);
			break;
		}
		case 0x97:
		{
			/* 151 DisplayString(O:Object*,I:StrRef*)
			 * This action displays the strref specified by the StrRef parameter
			 * in the message window, attributing the text to
			 * the specified object.
			 */
			core->DisplayMessage(act->integer1);
			break;
		}
		case 0xA7:
		{
			core->PlayMovie(act->string1);
			break;
		}

		case 134:
		{
			/* AttackReevaluate(O:Target*,I:ReevaluationPeriod*)
			 *  (134 0x86)
			 */
			Actor* targetActor = dynamic_cast<Actor*>(FindObject(act));
			if (thisActor != NULL && targetActor != NULL) {
				IE::point point = targetActor->NearestPoint(thisActor->Position());
				WalkTo* walkToAction = new WalkTo(thisActor, point);
				thisActor->AddAction(walkToAction);
				Attack* attackAction = new Attack(thisActor, targetActor);
				thisActor->AddAction(attackAction);
			}

			break;
		}
		case 198: // 0xc6
		{
			/* STARTDIALOGNOSET(O:OBJECT*) (198 0xc6) */
			// TODO: Implement more correctly.
			Actor* actor = dynamic_cast<Actor*>(FindObject(act));
			if (actor != NULL) {
				Dialogue* dialogueAction = new Dialogue(thisActor, actor);
				thisActor->AddAction(dialogueAction);
			}
			break;
		}
		case 207:
		{
			/* 207 MoveToPointNoInterrupt(P:Point*)
			 * This action causes the active creature to move to the specified coordinates.
			 * The action will update the position of creatures as stored in ARE files
			 * (first by setting the coordinates of the destination point, then by setting
			 * the coordinates of the current point once the destination is reached).
			 * Conditions are not checked until the destination point is reached.*/
			Actor* actor = dynamic_cast<Actor*>(fTarget.Target());
			if (actor != NULL) {
				WalkTo* walkTo = new WalkTo(actor, act->where);
				actor->AddAction(walkTo);
				actor->StopCheckingConditions();
			}
			break;
		}
		case 228: // 0xe4
		{
			/* CreateCreatureImpassable(S:NewObject*,P:Location*,I:Face*) (228 0xe4) */
			/* This action creates the specified creature
			 * on a normally impassable surface (e.g. on a wall,
			 * on water, on a roof). */
			Actor* actor = new Actor(act->string1, act->where, act->integer1);
			std::cout << "Created actor " << act->string1 << " on ";
			std::cout << act->where.x << ", " << act->where.y << std::endl;
			actor->SetDestination(act->where);
			RoomContainer::Get()->ActorEnteredArea(actor);
			break;
		}
		default:
			printf("SCRIPT: UNIMPLEMENTED ACTION!!!\n");
			printf("SCRIPT: %s (%d 0x%x)\n", IDTable::ActionAt(act->id).c_str(), act->id, act->id);
			act->Print();
			break;
	}

	return true;
}