Beispiel #1
0
bool AIIdea::CanUseCharacter(const Character & character)
{
  if (character.IsDead())
    return false;

  bool can_change_character = GameMode::GetInstance()->AllowCharacterSelection()
    && (Game::GetInstance()->ReadState() == Game::PLAYING)
    && !Game::GetInstance()->IsCharacterAlreadyChosen();
  return (character.IsActiveCharacter() || can_change_character);
}
//----------------------------------------------------------------------------
void GroupBuf::Update (double appSeconds, double elapsedSeconds)
{
	Buf::Update(appSeconds, elapsedSeconds);

	Scene *scene = PX2_PROJ.GetScene();
	Character *targetChar = DynamicCast<Character>(scene->GetActorByID(mToGroupCharacterID));
	if (targetChar)
	{
		mCharacter->SetGroup(targetChar->GetGroup());

		if (targetChar->IsDead() || targetChar->IsFreezed())
			SetOver(true);
	}
	else
	{
		SetOver(true);
	}
}
Beispiel #3
0
void Suicide::Refresh()
{
  // The suicide sound may play at different speed for different players,
  // that's why the explosion should not depend on the fact if the sound has finished playing or not.
  uint time_since_last_fire = Time::GetInstance()->Read() - m_last_fire_time;
  Character *player = &ActiveCharacter();
  if (m_last_fire_time > 0 && time_since_last_fire > SUICIDE_SOUND_DURATION_IN_MS && !player->IsDead()) {
    player->DisableDeathExplosion();
    player->body->MakeParticles(ActiveCharacter().GetPosition());
    player->SetEnergy(0, player); // Die!
    ApplyExplosion(player->GetCenter(), cfg());
  }
}
//----------------------------------------------------------------------------
bool Skill::Activate()
{
	Scene *scene = PX2_PROJ.GetScene();
	if (!scene) return false;

	if (!mCharacter)
		return false;

	if (!mFirstSkillStep)
		return false;

	if (mActivateAllowTimes >= 0)
	{
		if (mActivatedTimes >= mActivateAllowTimes)
			return false;
	}

	if (IsOnCD())
		return false;

	SkillController *skillComp = DynamicCast<SkillController>(
		mCharacter->GetControllerByName("SkillController"));
	if (skillComp)
	{
		assertion(false, "has no this component.");
		return false;
	}

	mIsActivatting = true;
	SetOnCD(true);
	SetOnCDTime(0.0f);

	float randomVal = Mathf::UnitRandom();
	if (randomVal > mActivateProbability)
		return true;

	mActivatedTimes++;

	const APoint &curPos = mCharacter->LocalTransform.GetTranslate();
	const AVector &faceDir = mCharacter->GetHeading();
	int aimTarget = skillComp->GetAimTarget();
	Character *aimChar = skillComp->GetAimTargetCharacter();
	int group = mCharacter->GetGroup();

	float radiusLength = GetMRadiusLength();
	float width = GetMWidth();
	float degree = GetMFanDegree();

	ShapeType shapeType = GetShapeType();
	int numRangeLock = GetNumRangeLock();
	AffectGroupType agt = GetAffectGroupType();

	if (NFT_NEAR == mNearFarType)
	{
		SkillInstance *inst = new0 SkillInstance(this);
		mSkillInstances.push_back(inst);

		int numAdded = 0;

		inst->SetAimTarget(aimTarget);

		if (IsRangeType()) // ·¶Ξ§
		{
			if (-1 == numRangeLock)
			{
				std::vector<Actor*> actors;
				scene->GetRangeActors(actors, curPos, radiusLength, true, GetSkillQueryBitSet());
				for (int i = 0; i < (int)actors.size(); i++)
				{
					Character *character = DynamicCast<Character>(actors[i]);

					if (character && !character->IsDead())
					{
						const APoint &targetPos = character->LocalTransform.GetTranslate();
						float targetRadius = character->GetRadius();

						if (IsInRange(curPos, radiusLength, width, faceDir, degree, targetPos,
							targetRadius, shapeType, false))
						{
							inst->AddTarget(character->GetID());
							numAdded++;
						}
					}
				}
			}
			else if (numRangeLock > 0)
			{
				if (AGT_SELF == agt)
				{
					inst->AddTarget(mCharacter->GetID());
					numAdded++;
				}

				std::vector<Actor*> actors;
				scene->GetRangeActors(actors, curPos, radiusLength, true, GetSkillQueryBitSet());
				for (int i = 0; i < (int)actors.size(); i++)
				{
					Character *character = DynamicCast<Character>(actors[i]);
					if (character && !character->IsDead() &&
						character != aimChar && character != mCharacter)
					{
						if ((AGT_ENEMYS == agt && character->GetGroup() != group) ||
							(AGT_SELF_GROUP==agt) && character->GetGroup()==group ||
							(AGT_SELF == agt && character->GetGroup() == group) ||
							(AGT_BOTH == agt))
						{
							const APoint &targetPos = character->LocalTransform.GetTranslate();
							float targetRadius = character->GetRadius();

							if (IsInRange(curPos, radiusLength, width, faceDir, degree, targetPos,
								targetRadius, shapeType, false) && numAdded < numRangeLock)
							{
								inst->AddTarget(character->GetID());
								numAdded++;
							}
						}
					}
				}
			}
		}
		else // µ¥Με
		{
			if (AGT_ENEMYS == agt || AGT_BOTH == agt)
			{
				Character *aimChar = skillComp->GetAimTargetCharacterAlive();
				if (aimChar && aimChar->IsContainAllBits(GetSkillQueryBitSet()))
				{
					const APoint &targetPos = aimChar->LocalTransform.GetTranslate();
					float targetRadius = aimChar->GetRadius();

					if (IsInRange(curPos, radiusLength, width, faceDir, degree, targetPos,
						targetRadius, shapeType, false))
					{
						inst->AddTarget(aimChar->GetID());
						numAdded++;
					}
				}
			}
			else if (AGT_SELF == agt)
			{
				inst->AddTarget(mCharacter->GetID());
				numAdded++;
			}
		}

		inst->Enter(mFirstSkillStep);
	}
	else
	{
		int multiAdd = 0;

		if (1 == mNumMultiInstance)
		{
			SkillInstance *inst = new0 SkillInstance(this);
			mSkillInstances.push_back(inst);
			inst->SetAimTarget(aimTarget);
			inst->Enter(mFirstSkillStep);

			multiAdd++;
		}
		else if (mNumMultiInstance > 1)
		{
			std::vector<Actor*> actors;
			scene->GetRangeActors(actors, curPos, radiusLength, true, GetSkillQueryBitSet());

			SkillInstance *inst = new0 SkillInstance(this);
			mSkillInstances.push_back(inst);

			if (AGT_ENEMYS == this->GetAffectGroupType())
			{
				inst->SetAimTarget(aimTarget);
			}
			else if (AGT_SELF == this->GetAffectGroupType())
			{
				inst->SetAimTarget(mCharacter->GetID());
			}

			inst->Enter(mFirstSkillStep);

			multiAdd++;

			for (int i = 0; i < (int)actors.size(); i++)
			{
				Character *character = DynamicCast<Character>(actors[i]);
				if (character && !character->IsDead() && character != aimChar && character != mCharacter)
				{
					SkillInstance *inst1 = new0 SkillInstance(this);
					mSkillInstances.push_back(inst1);
					inst1->SetAimTarget(character->GetID());
					inst->SetBeShared(true);
					inst1->Enter(mFirstSkillStep);

					multiAdd++;
				}

				if (multiAdd >= mNumMultiInstance)
					break;
			}
		}
	}

	return true;
}
void Chapter::Do(Character& character) const
{
  if (m_verbose) { std::clog << __func__ << std::endl; }
  Helper h;

  assert(m_observer);
  character.SetObserver(m_observer);

  if (m_verbose) { std::clog << "The first text comes now" << std::endl; }

  ShowText("\n");

  #ifndef NDEBUG
  ShowText("CHAPTER " + h.ToStr(GetChapterNumber()) + "\n");
  #endif

  //Display the text line by line
  ShowText(m_text + "\n");

  if (m_verbose) { std::clog << "The first text has been" << std::endl; }


  if (GetType() == ChapterType::game_lost)
  {
    m_game_lost_chapter.Do(character);
    assert(character.IsDead());
    return;
  }
  else if (GetType() == ChapterType::game_won)
  {
    ShowText("\n");
    m_game_won_chapter.Do(character);
    ShowText("\n");
    return;
  }
  else if (GetType() == ChapterType::play_dice)
  {
    m_dice_game_chapter.Do(character);
    m_consequence.Apply(character);
  }
  else if (GetType() == ChapterType::play_ball)
  {
    m_ball_game_chapter.Do(character);
    m_consequence.Apply(character);
  }
  else if (GetType() == ChapterType::play_pill)
  {
    m_pill_game_chapter.Do(character);
    if (character.IsDead()) return;
    m_consequence.Apply(character);
  }
  //Options
  else if (!GetOptions().GetOptions().empty())
  {
    if (GetOptions().GetValidOptions(character).empty())
    {
      std::cerr
        << "ERROR: no valid options in chapter " << character.GetCurrentChapter()
        << std::endl
        << "Options:\n"
      ;
      assert(GetOptions().GetOptions().size() == 2);
    }
    while (1)
    {
      if (m_verbose) { std::clog << "Let the use choose a valid option" << std::endl; }

      auto options = GetOptions().GetValidOptions(character);

      //If there are options, add (1) showing inventory (2) eating provision (3) drinking potion
      if (options.size() > 1)
      {
        //Add to show the inventory
        options.push_back(CreateShowInventoryOption());
        if (character.GetProvisions() > 0) { options.push_back(CreateEatProvisionOption()); }
        if (character.HasPotion()) { options.push_back(CreateDrinkPotionOption()); }
      }

      if (m_verbose) { std::clog << "Do the request" << std::endl; }

      assert(m_observer);
      const auto chosen = m_observer->RequestOption(options);

      if (m_verbose) { std::clog << "Done the request" << std::endl; }

      ShowText("\n");
      if (chosen.GetConsequence().GetType() == ConsequenceType::show_inventory)
      {
        //Showing the inventory is trivial
        this->ShowText(character.ShowInventory());
        continue;
      }
      if (chosen.GetConsequence().GetType() == ConsequenceType::eat_provision)
      {
        character.ChangeProvisions(-1);
        character.ChangeCondition(4);
        continue;
      }
      if (chosen.GetConsequence().GetType() == ConsequenceType::drink_potion)
      {
        character.DrinkPotion();
        continue;
      }

      chosen.DoChoose(character);
      assert(m_consequence.GetNextChapter() == -1);

      //Only apply these consequences once
      m_consequence.Apply(character);
      break;
    }
  }
  else if (GetType() == ChapterType::fight)
  {
    const int n_chapters_before{static_cast<int>(character.GetChapters().size())};
    m_fighting_chapter.Do(character);
    if (character.IsDead())
    {
      m_game_lost_chapter.Do(character);
      return;
    }

    assert(m_consequence.GetNextChapter() > 0);
    const int n_chapters_after{static_cast<int>(character.GetChapters().size())};
    if (n_chapters_after != n_chapters_before)
    {
      //Player has escaped
      //Check that there are no other consequences that need to be applied
      assert(m_consequence.GetChangeArrows() == 0);
      assert(m_consequence.GetChangeCondition() == 0);
      assert(m_consequence.GetChangeGold() == 0);
      assert(m_consequence.GetChangeLuck() == 0);
      assert(m_consequence.GetChangeProvisions() == 0);
      assert(m_consequence.GetChangeSkill() == 0);
      assert(m_consequence.GetItemsToAdd().empty());
      assert(m_consequence.GetItemsToRemove().empty());
    }
    else
    {
      m_consequence.Apply(character);
    }
  }
  else if (GetType() == ChapterType::test_your_luck)
  {
    GetLuck().Do(character);
  }
  else if (GetType() == ChapterType::test_your_skill)
  {
    GetSkill().Do(character);
  }
  else if (GetType() == ChapterType::shop)
  {
    GetShop().Do(character);
    m_consequence.Apply(character);
  }
  else if (GetType() == ChapterType::pawn_shop)
  {
    GetPawnShop().Do(character);
    m_consequence.Apply(character);
  }
  else if (GetType() == ChapterType::normal)
  {
    //Nothing
    m_consequence.Apply(character);
  }
  else
  {
    assert(!"Should not get here");
  }

  if (character.IsDead())
  {
    m_game_lost_chapter.Do(character);
    return;
  }

  ShowText(m_bye_text);
}