diff --git a/source/TouhouDanmakufu/Common/StgShot.cpp b/source/TouhouDanmakufu/Common/StgShot.cpp index 97e38007..a12393ec 100644 --- a/source/TouhouDanmakufu/Common/StgShot.cpp +++ b/source/TouhouDanmakufu/Common/StgShot.cpp @@ -186,7 +186,7 @@ void StgShotManager::AddShot(ref_unsync_ptr obj) { listObj_.push_back(obj); } -void StgShotManager::DeleteInCircle(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius) { +size_t StgShotManager::DeleteInCircle(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius) { int r = radius ? *radius : 0; int rr = r * r; @@ -195,6 +195,8 @@ void StgShotManager::DeleteInCircle(int typeDelete, int typeTo, int typeOwner, i int rect_x2 = cx + r; int rect_y2 = cy + r; + size_t res = 0; + for (ref_unsync_ptr& obj : listObj_) { if (obj->IsDeleted()) continue; if ((typeOwner != StgShotObject::OWNER_NULL) && (obj->GetOwnerType() != typeOwner)) continue; @@ -215,8 +217,60 @@ void StgShotManager::DeleteInCircle(int typeDelete, int typeTo, int typeOwner, i obj->SetFadeDelete(); else if (typeTo == TO_TYPE_ITEM) obj->ConvertToItem(false); + ++res; + } + } + + return res; +} +size_t StgShotManager::DeleteInRegularPolygon(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius, int edges, double angle) { + int r = radius ? *radius : 0; + + int rect_x1 = cx - r; + int rect_y1 = cy - r; + int rect_x2 = cx + r; + int rect_y2 = cy + r; + + size_t res = 0; + + for (ref_unsync_ptr& obj : listObj_) { + if (obj->IsDeleted()) continue; + if ((typeOwner != StgShotObject::OWNER_NULL) && (obj->GetOwnerType() != typeOwner)) continue; + if (typeDelete == DEL_TYPE_SHOT && obj->IsSpellResist()) continue; + + int sx = obj->GetPositionX(); + int sy = obj->GetPositionY(); + + bool bInPolygon = radius == nullptr; + if (!bInPolygon && ((sx > rect_x1 && sy > rect_y1) && (sx < rect_x2 && sy < rect_y2))) { + float f = GM_PI / (float) edges; + float cf = cosf(f); + float dx = sx - cx; + float dy = sy - cy; + float dist = hypotf(dy, dx); + + bInPolygon = dist <= r; + if (bInPolygon) { + double r_apothem = r * cf; + bInPolygon = dist <= r_apothem; + if (!bInPolygon) { + double ang = fmod(Math::NormalizeAngleRad(atan2(dy, dx)) - Math::DegreeToRadian(angle), 2 * f); + bInPolygon = dist <= (r_apothem / cos(ang - f)); + } + } + } + if (bInPolygon) { + if (typeTo == TO_TYPE_IMMEDIATE) + obj->DeleteImmediate(); + else if (typeTo == TO_TYPE_FADE) + obj->SetFadeDelete(); + else if (typeTo == TO_TYPE_ITEM) + obj->ConvertToItem(false); + ++res; } } + + return res; } std::vector StgShotManager::GetShotIdInCircle(int typeOwner, int cx, int cy, int* radius) { diff --git a/source/TouhouDanmakufu/Common/StgShot.hpp b/source/TouhouDanmakufu/Common/StgShot.hpp index 790dcf9b..32e5ea44 100644 --- a/source/TouhouDanmakufu/Common/StgShot.hpp +++ b/source/TouhouDanmakufu/Common/StgShot.hpp @@ -72,7 +72,8 @@ class StgShotManager { void SetShotDeleteClip(const DxRect& clip) { rcDeleteClip_ = clip; } DxRect* GetShotDeleteClip() { return &rcDeleteClip_; } - void DeleteInCircle(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius); + size_t DeleteInCircle(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius); + size_t DeleteInRegularPolygon(int typeDelete, int typeTo, int typeOwner, int cx, int cy, int* radius, int edges, double angle); std::vector GetShotIdInCircle(int typeOwner, int cx, int cy, int* radius); size_t GetShotCount(int typeOwner); size_t GetShotCountAll() { return listObj_.size(); } diff --git a/source/TouhouDanmakufu/Common/StgStageScript.cpp b/source/TouhouDanmakufu/Common/StgStageScript.cpp index f66d28e2..ebc0dcea 100644 --- a/source/TouhouDanmakufu/Common/StgStageScript.cpp +++ b/source/TouhouDanmakufu/Common/StgStageScript.cpp @@ -317,6 +317,7 @@ static const std::vector stgStageFunction = { //STG共通関数:弾 { "DeleteShotAll", StgStageScript::Func_DeleteShotAll, 2 }, { "DeleteShotInCircle", StgStageScript::Func_DeleteShotInCircle, 5 }, + { "DeleteShotInRegularPolygon", StgStageScript::Func_DeleteShotInRegularPolygon, 7 }, { "CreateShotA1", StgStageScript::Func_CreateShotA1, 6 }, { "CreateShotPA1", StgStageScript::Func_CreateShotPA1, 8 }, { "CreateShotA2", StgStageScript::Func_CreateShotA2, 8 }, //Deprecated, exists for compatibility @@ -1439,9 +1440,9 @@ gstd::value StgStageScript::Func_DeleteShotAll(gstd::script_machine* machine, in case TYPE_ITEM:typeTo = StgShotManager::TO_TYPE_ITEM; break; } - stageController->GetShotManager()->DeleteInCircle(typeDel, typeTo, StgShotObject::OWNER_ENEMY, 0, 0, nullptr); + size_t res = stageController->GetShotManager()->DeleteInCircle(typeDel, typeTo, StgShotObject::OWNER_ENEMY, 0, 0, nullptr); - return value(); + return script->CreateIntValue(res); } gstd::value StgStageScript::Func_DeleteShotInCircle(gstd::script_machine* machine, int argc, const gstd::value* argv) { StgStageScript* script = (StgStageScript*)machine->data; @@ -1465,9 +1466,37 @@ gstd::value StgStageScript::Func_DeleteShotInCircle(gstd::script_machine* machin case TYPE_ITEM:typeTo = StgShotManager::TO_TYPE_ITEM; break; } - stageController->GetShotManager()->DeleteInCircle(typeDel, typeTo, StgShotObject::OWNER_ENEMY, posX, posY, &radius); + size_t res = stageController->GetShotManager()->DeleteInCircle(typeDel, typeTo, StgShotObject::OWNER_ENEMY, posX, posY, &radius); - return value(); + return script->CreateIntValue(res); +} +gstd::value StgStageScript::Func_DeleteShotInRegularPolygon(gstd::script_machine* machine, int argc, const gstd::value* argv) { + StgStageScript* script = (StgStageScript*)machine->data; + StgStageController* stageController = script->stageController_; + + int typeDel = argv[0].as_int(); + int typeTo = argv[1].as_int(); + int posX = argv[2].as_real(); + int posY = argv[3].as_real(); + int radius = argv[4].as_real(); + int edges = argv[5].as_int(); + double angle = argv[6].as_real(); + + switch (typeDel) { + case TYPE_ALL:typeDel = StgShotManager::DEL_TYPE_ALL; break; + case TYPE_SHOT:typeDel = StgShotManager::DEL_TYPE_SHOT; break; + case TYPE_CHILD:typeDel = StgShotManager::DEL_TYPE_CHILD; break; + } + + switch (typeTo) { + case TYPE_IMMEDIATE:typeTo = StgShotManager::TO_TYPE_IMMEDIATE; break; + case TYPE_FADE:typeTo = StgShotManager::TO_TYPE_FADE; break; + case TYPE_ITEM:typeTo = StgShotManager::TO_TYPE_ITEM; break; + } + + size_t res = stageController->GetShotManager()->DeleteInRegularPolygon(typeDel, typeTo, StgShotObject::OWNER_ENEMY, posX, posY, &radius, edges, angle); + + return script->CreateIntValue(res); } gstd::value StgStageScript::Func_CreateShotA1(gstd::script_machine* machine, int argc, const gstd::value* argv) { StgStageScript* script = (StgStageScript*)machine->data; diff --git a/source/TouhouDanmakufu/Common/StgStageScript.hpp b/source/TouhouDanmakufu/Common/StgStageScript.hpp index c28d1cc6..a7c1e093 100644 --- a/source/TouhouDanmakufu/Common/StgStageScript.hpp +++ b/source/TouhouDanmakufu/Common/StgStageScript.hpp @@ -260,6 +260,7 @@ class StgStageScript : public StgControlScript { //STG共通関数:弾 static gstd::value Func_DeleteShotAll(gstd::script_machine* machine, int argc, const gstd::value* argv); static gstd::value Func_DeleteShotInCircle(gstd::script_machine* machine, int argc, const gstd::value* argv); + static gstd::value Func_DeleteShotInRegularPolygon(gstd::script_machine* machine, int argc, const gstd::value* argv); static gstd::value Func_CreateShotA1(gstd::script_machine* machine, int argc, const gstd::value* argv); static gstd::value Func_CreateShotPA1(gstd::script_machine* machine, int argc, const gstd::value* argv); static gstd::value Func_CreateShotA2(gstd::script_machine* machine, int argc, const gstd::value* argv); diff --git a/source/TouhouDanmakufu/DnhExecutor/th_dnh_poup.ico b/source/TouhouDanmakufu/DnhExecutor/th_dnh_poup.ico new file mode 100644 index 00000000..b01b11ca Binary files /dev/null and b/source/TouhouDanmakufu/DnhExecutor/th_dnh_poup.ico differ