/**
	This method should be called when the controller transitions to this state.
*/
void SimBiController::transitionToState(int stateIndex){
	setFSMStateTo(stateIndex);
	setStance(states[FSMStateIndex]->getStateStance(this->stance));
//	tprintf("Transition to state: %d (stance = %s) (phi = %lf)\n", stateIndex, (stance == LEFT_STANCE)?("left"):("right"), phi);
	//reset the phase...
	this->phi = 0;
}
SimBiController::SimBiController(Character* b) : PoseController(b){
	if (b == NULL)
		throwError("Cannot create a SIMBICON controller if there is no associated biped!!");
	//characters controlled by a simbicon controller are assumed to have: 2 feet
	lFoot = b->getARBByName("lFoot");
	rFoot = b->getARBByName("rFoot");

	if (rFoot == NULL || lFoot == NULL){
		lFoot = b->getARBByName("lFoot2");
		rFoot = b->getARBByName("rFoot2");
	}

	if (rFoot == NULL || lFoot == NULL)
		throwError("The biped must have the rigid bodies lFoot and rFoot!");
	
	//and two hips connected to the root
	Joint* lHip = b->getJointByName("lHip");
	Joint* rHip = b->getJointByName("rHip");

	lHipIndex = b->getJointIndex("lHip");
	rHipIndex = b->getJointIndex("rHip");

	if (rFoot == NULL || lFoot == NULL)
		throwError("The biped must have the joints lHip and rHip!");

	root = b->getRoot();
	
	if (lHip->getParent() != rHip->getParent() || lHip->getParent() != root)
		throwError("The biped's hips must have a common parent, which should be the root of the figure!");

	setStance(LEFT_STANCE);
	phi = 0;

	setFSMStateTo(-1);

	stanceHipDamping = -1;
	stanceHipMaxVelocity = 4;
	rootPredictiveTorqueScale = 0;

	bodyTouchedTheGround = false;
	
	startingState = -1;
	startingStance = LEFT_STANCE;
	initialBipState[0] = '\0';
}
/**
	This method loads all the pertinent information regarding the simbicon controller from a file.
*/
void SimBiController::loadFromFile(char* fName){
	if (fName == NULL)
		throwError("NULL file name provided.");
	FILE *f = fopen(fName, "r");
	if (f == NULL)
		throwError("Could not open file: %s", fName);

	//to be able to load multiple controllers from multiple files,
	//we will use this offset to make sure that the state numbers
	//mentioned in each input file are updated correctly
	int stateOffset = this->states.size();
	SimBiConState* tempState;
	int tempStateNr = -1;

	//have a temporary buffer used to read the file line by line...
	char buffer[200];
	//this is where it happens.

	while (!feof(f)){
		//get a line from the file...
		fgets(buffer, 200, f);
		if (feof(f))
			break;
		if (strlen(buffer)>195)
			throwError("The input file contains a line that is longer than ~200 characters - not allowed");
		char *line = lTrim(buffer);
		int lineType = getConLineType(line);
		switch (lineType) {
			case CON_PD_GAINS_START:
				readGains(f);
				break;
			case CON_STATE_START:
				tempState = new SimBiConState();
				sscanf(line, "%d", &tempStateNr);
				if (tempStateNr != stateOffset + this->states.size())
					throwError("Inccorect state offset specified: %d", tempStateNr);
				states.push_back(tempState);
				tempState->readState(f, stateOffset);
				//now we have to resolve all the joint names (i.e. figure out which joints they apply to).
				resolveJoints(tempState);
				break;
			case CON_STANCE_HIP_DAMPING:
				sscanf(line, "%lf", &stanceHipDamping);
				break;
			case CON_STANCE_HIP_MAX_VELOCITY:
				sscanf(line, "%lf", &stanceHipMaxVelocity);
				break;
			case CON_ROOT_PRED_TORQUE_SCALE:
				sscanf(line, "%lf", &rootPredictiveTorqueScale);
				break;
			case CON_CHARACTER_STATE:
				character->loadReducedStateFromFile(trim(line));
				strcpy(initialBipState, trim(line));
				break;
			case CON_START_AT_STATE:
				if (sscanf(line, "%d", &tempStateNr) != 1)
					throwError("A starting state must be specified!");
				transitionToState(tempStateNr);
				startingState = tempStateNr;
				break;
			case CON_COMMENT:
				break;
			case CON_STARTING_STANCE:
				if (strncmp(trim(line), "left", 4) == 0){
					setStance(LEFT_STANCE);
					startingStance = LEFT_STANCE;
				}
				else if (strncmp(trim(line), "right", 5) == 0){
					setStance(RIGHT_STANCE);
					startingStance = RIGHT_STANCE;
				}
				else 
					throwError("When using the \'reverseTargetOnStance\' keyword, \'left\' or \'right\' must be specified!");
				break;
			case CON_NOT_IMPORTANT:
				tprintf("Ignoring input line: \'%s\'\n", line);
				break;
			default:
				throwError("Incorrect SIMBICON input file: \'%s\' - unexpected line.", buffer);
		}
	}
}
Exemple #4
0
void _actorLogic(character *actor) {
	int moved = 0;

	if (!actor->hp) {
		return;
	}
	
	character *player = getPlayer(), *ptr = CHARACTERS;
	item *weaponPtr = NULL, *actorWeapon = actorGetItemWithFlag(actor, IS_WEAPON);
	int hitActor = 0;
	int nx = actor->x + actor->vx;
	int ny = actor->y + actor->vy;
	int spawnPosition[2];
	
	if (!actor->turns) {
		return;
	}
	
	if (actor->delay > 1) {
		actor->delay --;
		
		return;
	}
	
	actor->turns = 0;
	actor->delay = 0;

	if (actor->nextStanceFlagsToAdd) {
		tickSystemsWithMaskForEntity(getWorld(), actor->entityId, EVENT_ADD_STANCE);

		actor->stanceFlags |= actor->nextStanceFlagsToAdd;
		actor->nextStanceFlagsToAdd = 0x0;
	}

	if (actor->nextStanceFlagsToRemove) {
		tickSystemsWithMaskForEntity(getWorld(), actor->entityId, EVENT_REMOVE_STANCE);

		actor->stanceFlags ^= actor->nextStanceFlagsToRemove;
		
		if (actor->nextStanceFlagsToRemove & IS_STUNNED) {
			if (actor == player) {
				showMessage(5, "You regain composure.", NULL);
			} else {
				showMessage(5, "It regains composure.", NULL);
			}
		} else if (actor->nextStanceFlagsToRemove & IS_HOLDING_LODGED_WEAPON) {
			if (actor == player) {
				showMessage(5, "You dislodge the weapon.", NULL);
			} else {
				showMessage(5, "Something dislodges their weapon.", NULL);
			}
		}
		
		if (actor->nextStanceFlagsToRemove & IS_STUCK_WITH_LODGED_WEAPON) {
			weaponPtr = getItemLodgedInActor(actor);
			
			weaponPtr->itemFlags ^= IS_LODGED;
			weaponPtr->lodgedInActor = NULL;
		}
		
		actor->nextStanceFlagsToRemove = 0x0;
	}
	
	while (ptr != NULL) {
		if (ptr == actor || ptr->hp <= 0) {
			ptr = ptr->next;
			
			continue;
		}
		
		if (ptr->x == nx && ptr->y == ny) {
			hitActor = 1;
			
			break;
		}

		ptr = ptr->next;
	}
	
	if (_checkForTouchedItemAndHandle(actor, nx, ny)) {
		actor->vx = 0;
		actor->vy = 0;
		
		return;
	}

	if (hitActor) {
		actor->vx = 0;
		actor->vy = 0;

		if (attack(actor, ptr)) {
			return;
		}
	} else if (actor->vx || actor->vy) {
		if (actor->stanceFlags & IS_STUCK_WITH_LODGED_WEAPON && getItemLodgedInActor(actor)->owner) {
			printf("Cant move because of stuck weapon.\n");
			
			return;
		}
		
		if (actor->stanceFlags & IS_HOLDING_LODGED_WEAPON) {
			actor->stanceFlags ^= IS_HOLDING_LODGED_WEAPON;
			dropItem(actor, actorWeapon);
			
			printf("Handle letting go of weapon!\n");
			
			showMessage(10, "You let go of the weapon.", NULL);
			
			return;
		}
		
		if (isPositionWalkable(nx, ny)) {
			moved = 1;

			if (actor->aiFlags & IS_VOID_WORM && getRandomFloat(0, 1) > .95) {
				getOpenPositionInRoom(getRandomRoom(), spawnPosition);
				createVoidWorm(spawnPosition[0], spawnPosition[1]);
			}

			if (actor->aiFlags & IS_VOID_WORM) {
				createVoidWormTail(actor->x, actor->y);
			}

			actor->lastX = actor->x;
			actor->lastY = actor->y;
			actor->x = nx;
			actor->y = ny;
			setStance(actor, IS_MOVING);

			if (actor->itemLight) {
				actor->itemLight->fuel -= getLevel();
			}

			if (actor->stanceFlags & IS_STABBING) {
				actor->statStabCount --;

				if (!actor->statStabCount) {
					unsetStance(actor, IS_STABBING);
				}
			}

			TCOD_map_compute_fov(actor->fov, actor->x, actor->y, actor->sightRange, 1, FOV_SHADOW);
		} else {
			if (actor->stanceFlags & IS_MOVING) {
				unsetStance(actor, IS_MOVING);

				if (actor->stanceFlags & IS_STABBING) {
					actor->statStabCount = 0;
					unsetStance(actor, IS_STABBING);
				}
			}
		}
	} else {
		if (actor->stanceFlags & IS_MOVING) {
			unsetStance(actor, IS_MOVING);

			if (actor->stanceFlags & IS_STABBING) {
				actor->statStabCount = 0;
				unsetStance(actor, IS_STABBING);
			}
		}
	}

	if (moved) {
		_checkForItemCollisions(actor);
	}
	
	if (!(actor->aiFlags & IS_IMMUNE_TO_DARKNESS) && _checkIfPositionLit(actor)) {
		return;
	}
	
	if (actor->itemLight) {
		actor->itemLight->x = actor->x;
		actor->itemLight->y = actor->y;
	}

	actor->vx = 0;
	actor->vy = 0;
}