| 1 | #include "Library/LiveActor/ActorAreaFunction.h" |
| 2 | |
| 3 | #include "Library/Area/AreaInitInfo.h" |
| 4 | #include "Library/Area/AreaObj.h" |
| 5 | #include "Library/Area/AreaObjDirector.h" |
| 6 | #include "Library/Area/AreaObjGroup.h" |
| 7 | #include "Library/Area/AreaObjMtxConnecter.h" |
| 8 | #include "Library/Area/AreaObjUtil.h" |
| 9 | #include "Library/Area/IUseAreaObj.h" |
| 10 | #include "Library/Area/SwitchKeepOnAreaGroup.h" |
| 11 | #include "Library/Area/SwitchOnAreaGroup.h" |
| 12 | #include "Library/Area/ValidatorBase.h" |
| 13 | #include "Library/LiveActor/ActorFlagFunction.h" |
| 14 | #include "Library/LiveActor/ActorInitInfo.h" |
| 15 | #include "Library/LiveActor/ActorMovementFunction.h" |
| 16 | #include "Library/LiveActor/ActorPoseUtil.h" |
| 17 | #include "Library/LiveActor/ActorSceneInfo.h" |
| 18 | #include "Library/LiveActor/LiveActor.h" |
| 19 | #include "Library/Math/MathUtil.h" |
| 20 | #include "Library/Placement/PlacementFunction.h" |
| 21 | #include "Library/Player/PlayerUtil.h" |
| 22 | |
| 23 | namespace al { |
| 24 | |
| 25 | AreaObj* tryFindAreaObjPlayerOne(const PlayerHolder* holder, const char* name) { |
| 26 | s32 playerNum = getPlayerNumMax(holder); |
| 27 | |
| 28 | AreaObj* selectedAreaObj = nullptr; |
| 29 | for (s32 i = 0; i < playerNum; i++) { |
| 30 | if (isPlayerDead(holder, i)) |
| 31 | continue; |
| 32 | if (!isAreaTarget(actor: getPlayerActor(holder, i))) |
| 33 | continue; |
| 34 | const sead::Vector3f& playerPos = getPlayerPos(holder, i); |
| 35 | AreaObj* areaObj = tryFindAreaObj(areaUser: getPlayerActor(holder, i), name, position: playerPos); |
| 36 | if (areaObj && |
| 37 | (!selectedAreaObj || selectedAreaObj->getPriority() < areaObj->getPriority())) { |
| 38 | selectedAreaObj = areaObj; |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | return selectedAreaObj; |
| 43 | } |
| 44 | |
| 45 | AreaObj* tryFindAreaObjPlayerAll(const PlayerHolder* holder, const char* name) { |
| 46 | s32 playerNum = getPlayerNumMax(holder); |
| 47 | if (playerNum == 0) |
| 48 | return nullptr; |
| 49 | |
| 50 | AreaObjGroup* areaGroup = tryFindAreaObjGroup(areaUser: getPlayerActor(holder, 0), name); |
| 51 | if (!areaGroup) |
| 52 | return nullptr; |
| 53 | |
| 54 | s32 groupSize = areaGroup->getSize(); |
| 55 | AreaObj* selectedAreaObj = nullptr; |
| 56 | for (s32 i = 0; i < groupSize; i++) { |
| 57 | AreaObj* areaObj = areaGroup->getAreaObj(index: i); |
| 58 | AreaObj* currentAreaObject = nullptr; |
| 59 | for (s32 j = 0; j < playerNum; j++) { |
| 60 | if (isPlayerDead(holder, j)) |
| 61 | continue; |
| 62 | |
| 63 | const sead::Vector3f& playerPos = getPlayerPos(holder, j); |
| 64 | currentAreaObject = areaObj; |
| 65 | if (!areaObj->isInVolume(pos: playerPos)) { |
| 66 | currentAreaObject = nullptr; |
| 67 | break; |
| 68 | } |
| 69 | } |
| 70 | if (currentAreaObject && (!selectedAreaObj || selectedAreaObj->getPriority() < |
| 71 | currentAreaObject->getPriority())) { |
| 72 | selectedAreaObj = currentAreaObject; |
| 73 | } |
| 74 | } |
| 75 | return selectedAreaObj; |
| 76 | } |
| 77 | |
| 78 | AreaObj* createAreaObj(const ActorInitInfo& actorInitInfo, const char* name) { |
| 79 | AreaInitInfo areaInitInfo; |
| 80 | initAreaInitInfo(areaInfo: &areaInitInfo, actorInfo: actorInitInfo); |
| 81 | AreaObj* areaObj = new AreaObj(name); |
| 82 | areaObj->init(info: areaInitInfo); |
| 83 | return areaObj; |
| 84 | } |
| 85 | |
| 86 | void initAreaInitInfo(AreaInitInfo* areaInitInfo, const ActorInitInfo& actorInitInfo) { |
| 87 | initAreaInitInfo(areaInfo: areaInitInfo, placementInfo: *actorInitInfo.placementInfo, actorInfo: actorInitInfo); |
| 88 | } |
| 89 | |
| 90 | AreaObj* createLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) { |
| 91 | const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo; |
| 92 | PlacementInfo placementInfo; |
| 93 | getLinksInfoByIndex(linkPlacementInfo: &placementInfo, placementInfo: actorPlacementInfo, linkName: name, index: 0); |
| 94 | |
| 95 | AreaInitInfo areaInfo; |
| 96 | initAreaInitInfo(areaInfo: &areaInfo, placementInfo, actorInfo: initInfo); |
| 97 | |
| 98 | AreaObj* areaObj = new AreaObj(areaName); |
| 99 | areaObj->init(info: areaInfo); |
| 100 | return areaObj; |
| 101 | } |
| 102 | |
| 103 | void initAreaInitInfo(AreaInitInfo* areaInitInfo, const PlacementInfo& placementInfo, |
| 104 | const ActorInitInfo& actorInitInfo) { |
| 105 | areaInitInfo->set(placementInfo, stageSwitchDirector: actorInitInfo.stageSwitchDirector, |
| 106 | sceneObjHolder: actorInitInfo.actorSceneInfo.sceneObjHolder); |
| 107 | } |
| 108 | |
| 109 | AreaObj* tryCreateLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) { |
| 110 | s32 linkChildNum = calcLinkChildNum(initInfo, linkName: name); |
| 111 | if (linkChildNum < 1) |
| 112 | return nullptr; |
| 113 | |
| 114 | return createLinkArea(initInfo, name, areaName); |
| 115 | } |
| 116 | |
| 117 | __attribute__((always_inline)) AreaObjGroup* createLinkAreaGroup(const ActorInitInfo& initInfo, |
| 118 | const char* name, |
| 119 | const char* groupName, |
| 120 | const char* areaName) { |
| 121 | s32 linkChildNum = calcLinkChildNum(initInfo, linkName: name); |
| 122 | if (linkChildNum < 1) |
| 123 | return nullptr; |
| 124 | |
| 125 | AreaObjGroup* areaGroup = new AreaObjGroup(groupName, 0); |
| 126 | areaGroup->createBuffer(capacity: linkChildNum); |
| 127 | const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo; |
| 128 | |
| 129 | for (s32 i = 0; i < linkChildNum; i++) { |
| 130 | PlacementInfo placementInfo; |
| 131 | getLinksInfoByIndex(linkPlacementInfo: &placementInfo, placementInfo: actorPlacementInfo, linkName: name, index: i); |
| 132 | |
| 133 | AreaInitInfo areaInfo; |
| 134 | initAreaInitInfo(areaInitInfo: &areaInfo, placementInfo, actorInitInfo: initInfo); |
| 135 | |
| 136 | AreaObj* areaObj = new AreaObj(areaName); |
| 137 | areaObj->init(info: areaInfo); |
| 138 | |
| 139 | areaGroup->registerAreaObj(newAreaObj: areaObj); |
| 140 | } |
| 141 | return areaGroup; |
| 142 | } |
| 143 | |
| 144 | AreaObjGroup* createLinkAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo, const char* name, |
| 145 | const char* groupName, const char* areaName) { |
| 146 | return createLinkAreaGroup(initInfo, name, groupName, areaName); |
| 147 | } |
| 148 | |
| 149 | AreaObj* tryFindAreaObj(const LiveActor* actor, const char* name) { |
| 150 | if (!isAreaTarget(actor)) |
| 151 | return nullptr; |
| 152 | |
| 153 | return tryFindAreaObj(areaUser: actor, name, position: getTrans(actor)); |
| 154 | } |
| 155 | |
| 156 | bool isInAreaObj(const LiveActor* actor, const char* name) { |
| 157 | if (!isAreaTarget(actor)) |
| 158 | return false; |
| 159 | |
| 160 | return isInAreaObj(areaUser: actor, name, position: getTrans(actor)); |
| 161 | } |
| 162 | |
| 163 | bool isInDeathArea(const LiveActor* actor) { |
| 164 | if (!isAreaTarget(actor)) |
| 165 | return false; |
| 166 | |
| 167 | return isInDeathArea(areaUser: actor, position: getTrans(actor)); |
| 168 | } |
| 169 | |
| 170 | bool isInWaterArea(const LiveActor* actor) { |
| 171 | if (!isAreaTarget(actor)) |
| 172 | return false; |
| 173 | |
| 174 | return isInWaterArea(areaUser: actor, position: getTrans(actor)); |
| 175 | } |
| 176 | |
| 177 | bool isInPlayerControlOffArea(const LiveActor* actor) { |
| 178 | if (!isAreaTarget(actor)) |
| 179 | return false; |
| 180 | |
| 181 | return isInPlayerControlOffArea(areaUser: actor, position: getTrans(actor)); |
| 182 | } |
| 183 | |
| 184 | f32 calcWaterSinkDepth(const LiveActor* actor) { |
| 185 | return calcWaterSinkDepth(areaUser: actor, position: getTrans(actor)); |
| 186 | } |
| 187 | |
| 188 | void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx, |
| 189 | const ActorInitInfo& initInfo) { |
| 190 | areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx( |
| 191 | parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: nullptr); |
| 192 | } |
| 193 | |
| 194 | void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx, |
| 195 | const ActorInitInfo& initInfo, const ValidatorBase& validator) { |
| 196 | areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx( |
| 197 | parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: validator.fnc_8()); |
| 198 | } |
| 199 | |
| 200 | void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) { |
| 201 | registerAreaHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo); |
| 202 | } |
| 203 | |
| 204 | void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo, |
| 205 | const ValidatorBase& validator) { |
| 206 | registerAreaHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo, validator); |
| 207 | } |
| 208 | |
| 209 | void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx, |
| 210 | const ActorInitInfo& initInfo) { |
| 211 | areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx( |
| 212 | parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: nullptr); |
| 213 | } |
| 214 | |
| 215 | void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx, |
| 216 | const ActorInitInfo& initInfo, const ValidatorBase& validator) { |
| 217 | areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx( |
| 218 | parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: validator.fnc_8()); |
| 219 | } |
| 220 | |
| 221 | void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) { |
| 222 | registerAreaSyncHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo); |
| 223 | } |
| 224 | |
| 225 | void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo, |
| 226 | const ValidatorBase& validator) { |
| 227 | registerAreaSyncHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo, validator); |
| 228 | } |
| 229 | |
| 230 | bool tryReviseVelocityInsideAreaObj(sead::Vector3f* nearestEdgePos, LiveActor* actor, |
| 231 | AreaObjGroup* areaGroup, const AreaObj* areaObj) { |
| 232 | if (!areaGroup || !areaObj) |
| 233 | return false; |
| 234 | |
| 235 | if (!isInAreaObj(group: areaGroup, position: getTrans(actor))) { |
| 236 | calcNearestAreaObjEdgePos(outNearestEdgePos: nearestEdgePos, areaObj, position: getTrans(actor)); |
| 237 | setTrans(actor, trans: *nearestEdgePos); |
| 238 | setVelocityZero(actor); |
| 239 | return true; |
| 240 | } |
| 241 | |
| 242 | f32 velMagnitude = getVelocity(actor).length(); |
| 243 | sead::Vector3f nextPosition = getTrans(actor) + getVelocity(actor); |
| 244 | if (isInAreaObj(group: areaGroup, position: nextPosition)) |
| 245 | return false; |
| 246 | |
| 247 | calcNearestAreaObjEdgePos(outNearestEdgePos: nearestEdgePos, areaObj, position: nextPosition); |
| 248 | sead::Vector3f newVelocity = *nearestEdgePos - getTrans(actor); |
| 249 | if (newVelocity.length() > velMagnitude) |
| 250 | setLength(vec: &newVelocity, length: velMagnitude); |
| 251 | setVelocity(actor, vel: newVelocity); |
| 252 | return true; |
| 253 | } |
| 254 | |
| 255 | SwitchKeepOnAreaGroup* tryCreateSwitchKeepOnAreaGroup(LiveActor* actor, |
| 256 | const ActorInitInfo& initInfo) { |
| 257 | AreaObjGroup* areaGroup = |
| 258 | createLinkAreaGroup(actor, initInfo, name: "AreaSwitchKeepOn" , groupName: "子供スイッチキープエリアグループ" , |
| 259 | areaName: "子供スイッチキープエリア" ); |
| 260 | if (!areaGroup) |
| 261 | return nullptr; |
| 262 | |
| 263 | return new SwitchKeepOnAreaGroup(areaGroup); |
| 264 | } |
| 265 | |
| 266 | SwitchOnAreaGroup* tryCreateSwitchOnAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo) { |
| 267 | AreaObjGroup* areaGroup = createLinkAreaGroup( |
| 268 | actor, initInfo, name: "AreaSwitchOn" , groupName: "子供スイッチOnエリアグループ" , areaName: "子供スイッチOnエリア" ); |
| 269 | if (!areaGroup) |
| 270 | return nullptr; |
| 271 | |
| 272 | return new SwitchOnAreaGroup(areaGroup); |
| 273 | } |
| 274 | |
| 275 | } // namespace al |
| 276 | |