#include "d/t/d_t_tumble_weed.h" #include "c/c_math.h" #include "common.h" #include "d/a/obj/d_a_obj_tumble_weed.h" #include "d/col/bg/d_bg_s_gnd_chk.h" #include "d/d_sc_game.h" #include "f/f_profile_name.h" #include "m/m_vec.h" #include "s/s_Math.h" #include "toBeSorted/event_manager.h" SPECIAL_ACTOR_PROFILE(TUMBLE_WEED_TAG, dTgTumbleWeed_c, fProfile::TUMBLE_WEED_TAG, 0x0244, 0, 0); STATE_DEFINE(dTgTumbleWeed_c, AreaOut); STATE_DEFINE(dTgTumbleWeed_c, AreaIn); STATE_DEFINE(dTgTumbleWeed_c, Wind); void rodata_floats() { const f32 arr[] = {0.f, 0.8f, 20.f, 20.f, 5.f, 0.5f, 7.f}; } int dTgTumbleWeed_c::create() { mSpawnTimer = 0; mWindTimer = 150; mStateMgr.changeState(StateID_AreaOut); return SUCCEEDED; } int dTgTumbleWeed_c::doDelete() { return SUCCEEDED; } int dTgTumbleWeed_c::actorExecute() { mStateMgr.executeState(); sLib::calcTimer(&mSpawnTimer); return SUCCEEDED; } int dTgTumbleWeed_c::draw() { return SUCCEEDED; } void dTgTumbleWeed_c::initializeState_AreaOut() {} void dTgTumbleWeed_c::executeState_AreaOut() { if (sLib::calcTimer(&mWindTimer) == 0) { mWindTimer = 150; if (shouldDoWind()) { mStateMgr.changeState(StateID_Wind); return; } } if (isWithinPlayerRadius(mScale.x)) { mStateMgr.changeState(StateID_AreaIn); } } void dTgTumbleWeed_c::finalizeState_AreaOut() {} void dTgTumbleWeed_c::initializeState_AreaIn() {} void dTgTumbleWeed_c::executeState_AreaIn() { if (mSpawnTimer == 0) { if (shouldSpawnTumbleweed()) { doSpawnTumbleweed(); } mSpawnTimer = 600; } if (sLib::calcTimer(&mWindTimer) == 0) { mWindTimer = 150; if (shouldDoWind()) { mStateMgr.changeState(StateID_Wind); return; } } if (!isWithinPlayerRadius(mScale.x)) { mStateMgr.changeState(StateID_AreaOut); } } void dTgTumbleWeed_c::finalizeState_AreaIn() {} void dTgTumbleWeed_c::initializeState_Wind() { mVec3_c vec; getWind(vec); if (mSpawnedTumbleWeed.isLinked()) { mSpawnedTumbleWeed.get()->setWind(vec); } } void dTgTumbleWeed_c::executeState_Wind() { if (isWithinPlayerRadius(mScale.x)) { mStateMgr.changeState(StateID_AreaIn); } else { mStateMgr.changeState(StateID_AreaOut); } } void dTgTumbleWeed_c::finalizeState_Wind() {} bool dTgTumbleWeed_c::shouldSpawnTumbleweed() { return !mSpawnedTumbleWeed.isLinked() && cM::rnd() <= 0.8f && !EventManager::isInEvent(); } bool dTgTumbleWeed_c::shouldDoWind() { return mSpawnedTumbleWeed.isLinked() && cM::rnd() <= 0.5f; } void dTgTumbleWeed_c::doSpawnTumbleweed() { mVec3_c pos = mVec3_c::Ez; dCamera_c *pCam = dScGame_c::getCamera(0); if (pCam != nullptr) { mAng angle = pCam->getYRot(); f32 change; if (cM::rnd() < 0.5f) { change = cM::rndFX(5.f) * 182.f + 10923.f; } else { change = cM::rndFX(5.f) * 182.f + -10923.f; } angle += change; pos.rotY(angle); pos *= 600.f; pos += pCam->getPosition(); if (dBgS_ObjGndChk::CheckPos(pos + mVec3_c::Ey * 100.f)) { pos.y = dBgS_ObjGndChk::GetGroundHeight() + 10.f; } } dAcOTumbleWeed_c *pTumble = static_cast( dAcObjBase_c::create(fProfile::OBJ_TUMBLE_WEED, mRoomID, 0, &pos, nullptr, nullptr, 0xFFFFFFFF) ); if (pTumble == nullptr) { return; } mSpawnedTumbleWeed.link(pTumble); if (pCam != nullptr) { mAng rot = mAng::fromVec(mPosition - pos); f32 change; if (cM::rnd() < 0.5f) { change = cM::rndFX(5.f) * 182.f; } else { change = cM::rndFX(5.f) * -182.f; } rot += change; pTumble->mAngle.y = rot; pTumble->mSpeed = cM::rndFX(1.f) + 20.f; pTumble->mVelocity.y = 0.f; } } void dTgTumbleWeed_c::getWind(mVec3_c &pWind) { mVec3_c wind = mVec3_c::Ez; // @bug dir may not be initialized mAng dir; if (mSpawnedTumbleWeed.isLinked()) { dir = mSpawnedTumbleWeed.get()->getAngle().y; } f32 change; if (cM::rnd() < 0.5f) { change = cM::rndFX(15.f) * 182.f + 8192.f; } else { change = cM::rndFX(15.f) * 182.f + -8192.f; } dir += change; wind.rotY(dir); wind *= cM::rndFX(3.f) + 7.f; pWind = wind; }