void Avatar::checkTransform() { // handle transformation if (stats.transform_type != "" && stats.transform_type != "untransform" && stats.transformed == false) transform(); if (stats.transform_type != "" && stats.transform_duration == 0) untransform(); }
bool Dip::changePinLabels(bool singleRow, bool sip) { if (m_viewID != ViewLayer::SchematicView) return true; bool hasLocal = false; QStringList labels = getPinLabels(hasLocal); if (labels.count() == 0) return true; QString svg; if (singleRow) { svg = MysteryPart::makeSchematicSvg(labels, sip); } else { svg = Dip::makeSchematicSvg(labels); } QString chipLabel = modelPart()->localProp("chip label").toString(); if (!chipLabel.isEmpty()) { svg =TextUtils::replaceTextElement(svg, "label", chipLabel); } QTransform transform = untransform(); resetLayerKin(svg); resetConnectors(); retransform(transform); return true; }
/** * logic() * Handle a single frame. This includes: * - move the avatar based on buttons pressed * - calculate the next frame of animation * - calculate camera position based on avatar position * * @param action The actionbar power activated and the target. action.power == 0 means no power. * @param restrict_power_use Whether or not to allow power usage on mouse1 * @param npc True if the player is talking to an NPC. Can limit ability to move/attack in certain conditions */ void Avatar::logic(std::vector<ActionData> &action_queue, bool restrict_power_use, bool npc) { // hazards are processed after Avatar and Enemy[] // so process and clear sound effects from previous frames // check sound effects if (AUDIO) { if (play_sfx_phys) snd->play(sound_melee, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (play_sfx_ment) snd->play(sound_mental, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (play_sfx_hit) snd->play(sound_hit, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (play_sfx_die) snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if (play_sfx_critdie) snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); if(play_sfx_block) snd->play(sound_block, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false); // clear sound flags play_sfx_hit = false; play_sfx_phys = false; play_sfx_ment = false; play_sfx_die = false; play_sfx_critdie = false; play_sfx_block = false; } // clear current space to allow correct movement mapr->collider.unblock(stats.pos.x, stats.pos.y); // turn on all passive powers if ((stats.hp > 0 || stats.effects.triggered_death) && !respawn && !transform_triggered) powers->activatePassives(&stats); if (transform_triggered) transform_triggered = false; // handle when the player stops blocking if (stats.effects.triggered_block && !stats.blocking) { stats.cur_state = AVATAR_STANCE; stats.effects.triggered_block = false; stats.effects.clearTriggerEffects(TRIGGER_BLOCK); stats.refresh_stats = true; } stats.logic(); bool allowed_to_move; bool allowed_to_use_power = true; #ifdef __ANDROID__ const bool click_to_respawn = true; #else const bool click_to_respawn = false; #endif // check for revive if (stats.hp <= 0 && stats.effects.revive) { stats.hp = stats.get(STAT_HP_MAX); stats.alive = true; stats.corpse = false; stats.cur_state = AVATAR_STANCE; } // check level up if (stats.level < static_cast<int>(stats.xp_table.size()) && stats.xp >= stats.xp_table[stats.level]) { stats.level_up = true; stats.level++; std::stringstream ss; ss << msg->get("Congratulations, you have reached level %d!", stats.level); if (stats.level < stats.max_spendable_stat_points) { ss << " " << msg->get("You may increase one attribute through the Character Menu."); newLevelNotification = true; } log_msg = ss.str(); stats.recalc(); snd->play(sound_levelup); // if the player managed to level up while dead (e.g. via a bleeding creature), restore to life if (stats.cur_state == AVATAR_DEAD) { stats.cur_state = AVATAR_STANCE; } } // check for bleeding to death if (stats.hp == 0 && !(stats.cur_state == AVATAR_DEAD)) { stats.effects.triggered_death = true; stats.cur_state = AVATAR_DEAD; } // assist mouse movement if (!inpt->pressing[MAIN1]) { drag_walking = false; } // block some interactions when attacking if (!inpt->pressing[MAIN1] && !inpt->pressing[MAIN2]) { stats.attacking = false; } else if((inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) || (inpt->pressing[MAIN2] && !inpt->lock[MAIN2])) { stats.attacking = true; } // handle animation if (!stats.effects.stun) { activeAnimation->advanceFrame(); for (unsigned i=0; i < anims.size(); i++) { if (anims[i] != NULL) anims[i]->advanceFrame(); } } if (target_anim && target_anim->getTimesPlayed() >= 1) { target_visible = false; target_anim->reset(); } if (target_anim && target_visible) target_anim->advanceFrame(); // change the cursor if we're attacking if (action_queue.empty()) { lock_cursor = false; } else if (lock_cursor) { curs->setCursor(CURSOR_ATTACK); } // save a valid tile position in the event that we untransform on an invalid tile if (stats.transformed && mapr->collider.is_valid_position(stats.pos.x,stats.pos.y,MOVEMENT_NORMAL, true)) { transform_pos = stats.pos; transform_map = mapr->getFilename(); } switch(stats.cur_state) { case AVATAR_STANCE: setAnimation("stance"); // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_move = restrict_power_use && (!inpt->lock[MAIN1] || drag_walking) && !lockAttack && !npc; allowed_to_use_power = !allowed_to_move; } else { allowed_to_move = true; allowed_to_use_power = true; } // handle transitions to RUN if (allowed_to_move) set_direction(); if (pressing_move() && allowed_to_move) { if (MOUSE_MOVE && inpt->pressing[MAIN1]) { inpt->lock[MAIN1] = true; drag_walking = true; } if (move()) { // no collision stats.cur_state = AVATAR_RUN; } } if (MOUSE_MOVE && !inpt->pressing[MAIN1]) { inpt->lock[MAIN1] = false; lockAttack = false; } break; case AVATAR_RUN: setAnimation("run"); if (!sound_steps.empty()) { int stepfx = rand() % static_cast<int>(sound_steps.size()); if (activeAnimation->isFirstFrame() || activeAnimation->isActiveFrame()) snd->play(sound_steps[stepfx]); } // allowed to move or use powers? if (MOUSE_MOVE) { allowed_to_use_power = !(restrict_power_use && !inpt->lock[MAIN1]); } else { allowed_to_use_power = true; } // handle direction changes set_direction(); // handle transition to STANCE if (!pressing_move()) { stats.cur_state = AVATAR_STANCE; break; } else if (!move()) { // collide with wall stats.cur_state = AVATAR_STANCE; break; } if (activeAnimation->getName() != "run") stats.cur_state = AVATAR_STANCE; break; case AVATAR_ATTACK: setAnimation(attack_anim); if (MOUSE_MOVE) lockAttack = true; if (activeAnimation->isFirstFrame() && attack_anim == "swing") snd->play(sound_melee); if (activeAnimation->isFirstFrame() && attack_anim == "cast") snd->play(sound_mental); // do power if (activeAnimation->isActiveFrame()) { // some powers check if the caster is blocking a tile // so we block the player tile prematurely here mapr->collider.block(stats.pos.x, stats.pos.y, false); powers->activate(current_power, &stats, act_target); hero_cooldown[current_power] = powers->getPower(current_power).cooldown; } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != attack_anim) { stats.cur_state = AVATAR_STANCE; stats.cooldown_ticks += stats.cooldown; } break; case AVATAR_BLOCK: setAnimation("block"); stats.blocking = false; break; case AVATAR_HIT: setAnimation("hit"); if (activeAnimation->isFirstFrame()) { stats.effects.triggered_hit = true; } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "hit") { stats.cur_state = AVATAR_STANCE; } break; case AVATAR_DEAD: allowed_to_use_power = false; if (stats.effects.triggered_death) break; if (stats.transformed) { stats.transform_duration = 0; untransform(); } setAnimation("die"); if (!stats.corpse && activeAnimation->isFirstFrame() && activeAnimation->getTimesPlayed() < 1) { stats.effects.clearEffects(); // raise the death penalty flag. Another module will read this and reset. stats.death_penalty = true; // close menus in GameStatePlay close_menus = true; snd->play(sound_die); if (stats.permadeath) { log_msg = msg->get("You are defeated. Game over! Press Enter to exit to Title."); } else { log_msg = msg->get("You are defeated. Press Enter to continue."); } // if the player is attacking, we need to block further input if (inpt->pressing[MAIN1]) inpt->lock[MAIN1] = true; } if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "die") { stats.corpse = true; } // allow respawn with Accept if not permadeath if (inpt->pressing[ACCEPT] || (click_to_respawn && inpt->pressing[MAIN1] && !inpt->lock[MAIN1])) { if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true; if (click_to_respawn && inpt->pressing[MAIN1]) inpt->lock[MAIN1] = true; mapr->teleportation = true; mapr->teleport_mapname = mapr->respawn_map; if (stats.permadeath) { // set these positions so it doesn't flash before jumping to Title mapr->teleport_destination.x = stats.pos.x; mapr->teleport_destination.y = stats.pos.y; } else { respawn = true; // set teleportation variables. GameEngine acts on these. mapr->teleport_destination.x = mapr->respawn_point.x; mapr->teleport_destination.y = mapr->respawn_point.y; } } break; default: break; } // handle power usage if (allowed_to_use_power) handlePower(action_queue); // calc new cam position from player position // cam is focused at player position mapr->cam.x = stats.pos.x; mapr->cam.y = stats.pos.y; // check for map events mapr->checkEvents(stats.pos); // decrement all cooldowns for (unsigned i = 0; i < hero_cooldown.size(); i++) { hero_cooldown[i]--; if (hero_cooldown[i] < 0) hero_cooldown[i] = 0; } // make the current square solid mapr->collider.block(stats.pos.x, stats.pos.y, false); }