/** 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); } } }
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; }