Last active
August 29, 2015 14:05
-
-
Save himika/ec01678047182d2cb9e7 to your computer and use it in GitHub Desktop.
近くに配置されているオブジェクトを、配列で一気に取得する関数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <skse.h> | |
#include <skse/GameForms.h> | |
#include <skse/GameData.h> | |
#include <skse/GameReferences.h> | |
#include <skse/GamePapyrusFunctions.h> | |
#include <list> | |
/* ============================================================== | |
scriptname HogeHoge hidden | |
; 近くに配置されているオブジェクトを、配列で一気に取得する | |
; afRadius ... 取得距離。この距離より短いものだけ取得。 | |
ObjectReference[] GetCloseReference(float afRadius) global native | |
=================================================================*/ | |
// グリッド状に配置されているセルの情報 | |
// 大きさは skyrim.ini [General] uGridsToLoad に依存 | |
class GridCellArray | |
{ | |
public: | |
virtual ~GridCellArray(); | |
UInt32 unk04; | |
UInt32 unk08; | |
UInt32 size; | |
TESObjectCELL** cells; | |
}; | |
class HogeHoge | |
{ | |
public: | |
// 近くに配置されているオブジェクトを、配列で一気に取得する | |
static VMArray<TESObjectREFR*> GetCloseReferences(float fRadius) | |
{ | |
PlayerCharacter* player = *g_thePlayer; | |
GridCellArray* arr = (GridCellArray*)(*g_TES)->gridCellArray; | |
double fRadiusSquare = fRadius * fRadius; | |
// 隣接しているセルをすべて走査 | |
typedef std::pair<TESObjectREFR*, double> Pair; // TESObjectREFR* と double の ペア | |
std::list<Pair> list; | |
int x, y; | |
for (x = 0; x < arr->size; x++) | |
{ | |
for (y = 0; y < arr->size; y++) | |
{ | |
TESObjectCELL* cell = arr->cells[x+y*arr->size]; | |
if (cell->unk30 != 7) // 逆アセンブルで割り出した何かの数値。 | |
continue; | |
// セルに配置されているTESObjectREFR*を走査 | |
TESObjectREFR* ref = NULL; | |
int i = 0; | |
while (cell->objectList.GetNthItem(i++, ref)) | |
{ | |
if (!ref || ref == player) | |
continue; | |
if (ref->GetNiNode()) // NiNodeが取得できる == 3Dがロード済み | |
{ | |
double dx = ref->pos.x - player->pos.x; | |
double dy = ref->pos.y - player->pos.y; | |
double dz = ref->pos.z - player->pos.z; | |
double d2 = dx*dx + dy*dy + dz*dz; | |
if (d2 < fRadiusSquare) | |
{ | |
Pair pair(ref, d2); | |
list.push_back(pair); | |
} | |
} | |
} | |
} | |
} | |
// 距離が短い順でリストを並び替え | |
list.sort( [](Pair a, Pair b) {return a.second < b.second;} ); | |
// list<Pair> を VMArray<TESObjectREFR*>に移し替える | |
VMArray<TESObjectREFR*> result; | |
if (list.size() > 0) | |
{ | |
result.Allocate((list.size() < 127) ? list.size() : 127); | |
int n = 0; | |
while (list.size() > 0) | |
{ | |
TESObjectREFR* ref = list.front().first; | |
list.pop_front(); | |
result.Set(&ref, n++); | |
if (result.Length() >= 127) // Papyrusだと、配列は127までしか扱えない | |
break; | |
} | |
} | |
return result; | |
} | |
}; | |
void RegisterPapyrusFunction() | |
{ | |
VMClassRegistry* registry = (*g_skyrimVM)->GetClassRegistry(); | |
REGISTER_PAPYRUS_FUNCTION(HogeHoge, GetCloseReferences, registry); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment