new service files - updates to ll-stack-architecture.md
This commit is contained in:
32
guides-stack/llama-alpha.service
Normal file
32
guides-stack/llama-alpha.service
Normal file
@@ -0,0 +1,32 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - alpha (meta/combat/action_eval on Ada #1)
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="CUDA_VISIBLE_DEVICES=0"
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=/data/llama.cpp/build/bin/llama-server \
|
||||
--model /data/models/prod/alpha/Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf \
|
||||
--model-draft /data/models/prod/alpha/mtp-gemma-4-31B-it.gguf \
|
||||
--spec-type draft-mtp \
|
||||
-fa on \
|
||||
--alias alpha \
|
||||
--host 0.0.0.0 \
|
||||
--port 31001 \
|
||||
--n-gpu-layers 40 \
|
||||
--ctx-size 65536 \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--batch-size 2048 \
|
||||
--ubatch-size 512 \
|
||||
--threads 8 \
|
||||
--cont-batching \
|
||||
--reasoning off
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
32
guides-stack/llama-beta.service
Normal file
32
guides-stack/llama-beta.service
Normal file
@@ -0,0 +1,32 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - beta (meta/combat/action_eval on Ada #1)
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="CUDA_VISIBLE_DEVICES=1"
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=/data/llama.cpp/build/bin/llama-server \
|
||||
--model /data/models/prod/beta/Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf \
|
||||
--model-draft /data/models/prod/beta/mtp-gemma-4-31B-it.gguf \
|
||||
--spec-type draft-mtp \
|
||||
-fa on \
|
||||
--alias beta \
|
||||
--host 0.0.0.0 \
|
||||
--port 31002 \
|
||||
--n-gpu-layers 40 \
|
||||
--ctx-size 65536 \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--batch-size 2048 \
|
||||
--ubatch-size 512 \
|
||||
--threads 8 \
|
||||
--cont-batching \
|
||||
--reasoning off
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
31
guides-stack/llama-delta.service
Normal file
31
guides-stack/llama-delta.service
Normal file
@@ -0,0 +1,31 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - delta
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=/usr/local/bin/llama-server \
|
||||
--model /data/models/prod/delta/Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf \
|
||||
--model-draft /data/models/prod/delta/mtp-gemma-4-31B-it.gguf \
|
||||
--spec-type draft-mtp \
|
||||
-fa on \
|
||||
--alias delta \
|
||||
--host 0.0.0.0 \
|
||||
--port 31001 \
|
||||
--n-gpu-layers 60 \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--ctx-size 262144 \
|
||||
--batch-size 2048 \
|
||||
--ubatch-size 512 \
|
||||
--threads 8 \
|
||||
--cont-batching \
|
||||
--reasoning off
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
31
guides-stack/llama-epsilon.service
Normal file
31
guides-stack/llama-epsilon.service
Normal file
@@ -0,0 +1,31 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - epsilon
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=/usr/local/bin/llama-server \
|
||||
--model /data/models/prod/epsilon/Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf \
|
||||
--model-draft /data/models/prod/epsilon/mtp-gemma-4-31B-it.gguf \
|
||||
--spec-type draft-mtp \
|
||||
-fa on \
|
||||
--alias epsilon \
|
||||
--host 0.0.0.0 \
|
||||
--port 31002 \
|
||||
--n-gpu-layers 60 \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--ctx-size 262144 \
|
||||
--batch-size 2048 \
|
||||
--ubatch-size 512 \
|
||||
--threads 8 \
|
||||
--cont-batching \
|
||||
--reasoning off
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
31
guides-stack/llama-gamma.service
Normal file
31
guides-stack/llama-gamma.service
Normal file
@@ -0,0 +1,31 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - gamma (memory/profile/vision/translator on RTX 3090)
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=/data/llama.cpp/build/bin/llama-server \
|
||||
--model /data/models/prod/gamma/Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf \
|
||||
--model-draft /data/models/prod/gamma/mtp-gemma-4-31B-it.gguf \
|
||||
--spec-type draft-mtp \
|
||||
-fa on \
|
||||
--alias gamma \
|
||||
--host 0.0.0.0 \
|
||||
--port 31003 \
|
||||
--n-gpu-layers 40 \
|
||||
--ctx-size 262144 \
|
||||
--cache-type-k q4_0 \
|
||||
--cache-type-v q4_0 \
|
||||
--batch-size 2048 \
|
||||
--ubatch-size 512 \
|
||||
--threads 8 \
|
||||
--cont-batching \
|
||||
--reasoning off
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
guides-stack/llama-zeta.service
Normal file
23
guides-stack/llama-zeta.service
Normal file
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=llama.cpp server - zeta
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nyx-organs
|
||||
Group=nimmerverse-agents
|
||||
Environment="PATH=/usr/local/cuda/bin:/data/venvs/llama/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin"
|
||||
ExecStart=llama-server \
|
||||
--model /data/models/prod/zeta/Huihui-Qwen3-VL-8B-Instruct-abliterated.Q8_0.gguf \
|
||||
--alias zeta \
|
||||
--mmproj /data/models/prod/zeta/zeta-mmproj-Q8_0.gguf \
|
||||
--host 0.0.0.0 \
|
||||
--port 31003 \
|
||||
--n-gpu-layers 9999 \
|
||||
--ctx-size 64000 \
|
||||
--chat-template-kwargs '{"enable_thinking": false}'
|
||||
RestartSec=5
|
||||
WorkingDirectory=/data
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -5,44 +5,42 @@ Chat endpoint: `/v1/chat/completions` with `{"chat_template_kwargs": {"enable_th
|
||||
|
||||
## Instances
|
||||
|
||||
| Instance | Node | GPU | Port | Model | Quant | VRAM | Vision |
|
||||
|----------|------|-----|------|-------|-------|------|--------|
|
||||
| **nyx** | theia | Blackwell 6000 | 31000 | self-trained ~41B | BF16 | ~84GB | ✅ |
|
||||
| **alpha1** | dioscuri | Ada #1 | 31001 | Qwen3.6-27B-Fable-711 | IQ4_XS | 16.6GB | ❌ |
|
||||
| **alpha2** | dioscuri | Ada #2 | 31002 | Qwen3.6-27B-Fable-711 | IQ4_XS | 16.6GB | ❌ |
|
||||
| **gamma** | comfy-dev | RTX 3090 | 31003 | Qwen3.6-27B-Fable-711-MTP | Q4_K_S MTP | 19.9GB | ✅ |
|
||||
| Instance | Node | GPU | Port | Model | Quant | Vision |
|
||||
|----------|------|-----|------|-------|-------|------|
|
||||
| **alpha** | dioscuri | Ada #1 | 31001 | Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf-MTP | Q4_K_M MTP
|
||||
| **beta** | dioscuri | Ada #2 | 31002 | Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf-MTP | Q4_K_M MTP
|
||||
| **gamma** | comfy-dev | RTX 3090 | 31003 | Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf-MTP | Q4_K_M MTP
|
||||
| **delta** | theia | Blackwell 6000 | 31001 | Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf-MTP | Q4_K_M MTP
|
||||
| **epsilon** | theia | Blackwell 6000 | 31002 | Gemma4-31B-QAT-Uncensored-HauhauCS-Balanced-Q4_K_M.gguf-MTP | Q4_K_M MTP
|
||||
| **zeta** | theia | Blackwell 6000 | 31003 | Huihui-Qwen3-VL-8B-Instruct-abliterated.Q8_0.gguf | Q8_0 | mmproj-Q8_0.gguf
|
||||
|
||||
## Role Mapping
|
||||
## Service Files under:
|
||||
/nimmerverse/nimmersky/guides-stack/
|
||||
|
||||
- **nyx (31000):** default dialogue, diary, agent_helper
|
||||
- **alpha1 (31001):** meta, combat, action_evaluation
|
||||
- **alpha2 (31002):** gamemaster, overflow
|
||||
- **gamma (31003):** memory, character_profile, vision, universal_translator
|
||||
llama-alpha.service
|
||||
llama-beta.service
|
||||
llama-delta.service
|
||||
llama-epsilon.service
|
||||
llama-gamma.service
|
||||
llama-zeta.service
|
||||
##
|
||||
## Theia specific
|
||||
|
||||
## Endpoints for SkyrimNet
|
||||
sudo nvidia-cuda-mps-control -d
|
||||
|
||||
```yaml
|
||||
default: 10.0.40.21:31000/v1
|
||||
diary: 10.0.40.21:31000/v1
|
||||
agent_helper: 10.0.40.21:31000/v1
|
||||
meta: 10.0.40.22:31001/v1
|
||||
combat: 10.0.40.22:31001/v1
|
||||
action_evaluation: 10.0.40.22:31001/v1
|
||||
gamemaster: 10.0.40.22:31002/v1
|
||||
memory: 10.0.30.124:31003/v1
|
||||
character_profile: 10.0.30.124:31003/v1
|
||||
vision: 10.0.30.124:31003/v1
|
||||
universal_translator: 10.0.30.124:31003/v1
|
||||
```
|
||||
This command starts the CUDA Multi-Process Service (MPS) control daemon in the background.
|
||||
|
||||
## Notes
|
||||
The control program used to manage the MPS server system.-d (Daemon mode): This flag launches the MPS control daemon in the background.What it does: Normally, if multiple Linux processes try to use the same GPU simultaneously, the GPU time-slices between them (hardware context switching), which adds overhead. MPS allows multiple different processes to share a single GPU context. This lets them execute kernels simultaneously on the same GPU, filling up underutilized GPU hardware and improving overall throughput.
|
||||
##
|
||||
|
||||
- Throughput: gamma ~20 tok/s, alpha1 ~10 tok/s, alpha2 ~14 tok/s
|
||||
- alpha1/alpha2 identical models (SHA256 confirmed)
|
||||
- gamma has MTP quant; alpha1/alpha2 have non-MTP
|
||||
- All llama.cpp services run as nyx-organs:nimmerverse-agents
|
||||
- OStimNet: Fable-Fusion needs explicit x-rated vocabulary in system prompts
|
||||
sudo nvidia-smi -i 0 -c EXCLUSIVE_PROCESS
|
||||
|
||||
## Service Files
|
||||
This command changes the Compute Mode of a specific GPU so that only one process can attach to it at a time.
|
||||
|
||||
`~/tmp/skyrimnet-analysis/services/` — llama-gamma.service, llama-alpha1.service, llama-alpha2.service
|
||||
nvidia-smi: The NVIDIA System Management Interface utility.
|
||||
-i 0 (Index 0): Targets the specific GPU with an ID of 0.
|
||||
-c EXCLUSIVE_PROCESS (Compute Mode): Sets the compute mode to "Exclusive Process"
|
||||
|
||||
.What it does: It restricts the GPU so that only one single CUDA context (process) can access it at any given time. If a second process tries to use GPU 0 while the first is running, it will immediately throw an out-of-memory or initialization error.
|
||||
##
|
||||
💡 How They Work TogetherAt first glance, these two commands seem to contradict each other: one allows sharing (MPS), and the other forbids sharing (EXCLUSIVE_PROCESS).However, they are designed to be used together. When you set a GPU to EXCLUSIVE_PROCESS, the MPS server counts as that single allowed process.EXCLUSIVE_PROCESS blocks all regular user applications from touching GPU 0 directly.MPS daemon steps in as the sole owner of GPU 0.Your applications then talk to the MPS daemon, which safely multiplexes their workloads onto the GPU together.This specific combination is the recommended way to deploy MPS because it prevents rogue, non-MPS processes from accidentally hijacking the GPU and ruining performance.
|
||||
@@ -0,0 +1,270 @@
|
||||
unit ExportScripts;
|
||||
|
||||
//version 1.0
|
||||
|
||||
// Global variables
|
||||
var ArmoList : TStringList;
|
||||
var ArmaList : TStringList;
|
||||
var ArmoListSlot : TStringList;
|
||||
var ArmaListSlot : TStringList;
|
||||
var RetrieveAddRaces : Boolean;
|
||||
|
||||
// Called when the script starts
|
||||
function Initialize : integer;
|
||||
var
|
||||
csvHeaderArmo: string;
|
||||
csvHeaderArma: string;
|
||||
begin
|
||||
csvHeaderArma := 'Plugin;RecordType;FormID;EditorID;Slot;Race;MaleModel;FemaleModel;MaleModel1stPerson;FemaleModel1stPerson;AdditionalRaces';
|
||||
csvHeaderArmo := 'Plugin;RecordType;FormID;EditorID;Slot;Race;Name;MaleModel;FemaleModel;Type;Enchantment;ArmorRating;Weight;Value;Keywords;ArmorAddon';
|
||||
|
||||
ArmoList := TStringList.Create;
|
||||
ArmoList.Add(csvHeaderArmo);
|
||||
|
||||
ArmaList := TStringList.Create;
|
||||
ArmaList.Add(csvHeaderArma);
|
||||
|
||||
ArmoListSlot := TStringList.Create;
|
||||
ArmoListSlot.Add(csvHeaderArmo);
|
||||
|
||||
ArmaListSlot := TStringList.Create;
|
||||
ArmaListSlot.Add(csvHeaderArma);
|
||||
|
||||
//don't retrieve 'Additional Races', takes too long
|
||||
RetrieveAddRaces := False
|
||||
end;
|
||||
|
||||
// Called for each selected record in the TES5Edit tree
|
||||
function Process(e: IInterface): integer;
|
||||
var
|
||||
i: integer;
|
||||
slot: cardinal;
|
||||
espName: string;
|
||||
recordType: string;
|
||||
itemName: string;
|
||||
maleModel: string;
|
||||
femaleModel: string;
|
||||
armorType: string;
|
||||
nArmorType: integer;
|
||||
typesList: array[0..2] of string;
|
||||
enchantment: string;
|
||||
rating: float;
|
||||
weight: float;
|
||||
value: integer;
|
||||
maleModel1st: string;
|
||||
femaleModel1st: string;
|
||||
keywords: string;
|
||||
armature: string;
|
||||
elKwda: IInterface;
|
||||
elArma: IInterface;
|
||||
elRaces: IInterface;
|
||||
slotList: TStringList;
|
||||
formId: string;
|
||||
primaryRace: string;
|
||||
additionalRaces: string;
|
||||
|
||||
begin
|
||||
if ((Signature(e) <> 'ARMO') and (Signature(e) <> 'ARMA')) then Exit;
|
||||
|
||||
typesList[0] := 'Light';
|
||||
typesList[1] := 'Heavy';
|
||||
typesList[2] := 'None';
|
||||
|
||||
slotList := TStringList.Create;
|
||||
itemName := '';
|
||||
armorType := '';
|
||||
maleModel := '';
|
||||
femaleModel := '';
|
||||
enchantment := '';
|
||||
maleModel1st := '';
|
||||
femaleModel1st := '';
|
||||
keywords := '';
|
||||
rating := 0.0;
|
||||
weight := 0.0;
|
||||
value := 0.0;
|
||||
formId := IntToHex(GetLoadOrderFormID(e), 8);
|
||||
slotList.Delimiter := ',';
|
||||
primaryRace := '';
|
||||
|
||||
espName := '[' + IntToStr(GetLoadOrder(GetFile(e))) + '] ' + GetFileName(e);
|
||||
if ElementExists(e,'FULL') then itemName := GetElementEditValues(e, 'FULL');
|
||||
if ElementExists(e,'EITM') then enchantment := GetElementEditValues(e, 'EITM');
|
||||
if ElementExists(e,'DNAM') then rating := GetElementNativeValues(e, 'DNAM');
|
||||
if ElementExists(e,'DATA\Value') then value := GetElementNativeValues(e, 'DATA\Value');
|
||||
if ElementExists(e,'DATA\Weight') then weight := GetElementNativeValues(e, 'DATA\Weight');
|
||||
if ElementExists(e,'RNAM') then primaryRace := GetElementEditValues(e, 'RNAM');
|
||||
|
||||
if ElementExists(e,'BODT\First Person Flags') then
|
||||
begin
|
||||
slot := GetElementNativeValues(e, 'BODT\First Person Flags');
|
||||
if ElementExists(e,'BODT\Armor Type') then
|
||||
begin
|
||||
nArmorType := GetElementNativeValues(e, 'BODT\Armor Type');
|
||||
armorType := typesList[nArmorType];
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
if ElementExists(e,'BOD2\First Person Flags') then
|
||||
begin
|
||||
slot := GetElementNativeValues(e, 'BOD2\First Person Flags');
|
||||
if ElementExists(e,'BOD2\Armor Type') then
|
||||
begin
|
||||
nArmorType := GetElementNativeValues(e, 'BOD2\Armor Type');
|
||||
armorType := typesList[nArmorType];
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
AddMessage('********* element doesnt have slot definition *********');
|
||||
Exit;
|
||||
end
|
||||
end;
|
||||
|
||||
if Signature(e) = 'ARMA' then
|
||||
begin
|
||||
if ElementExists(e,'Male world model\MOD2') then maleModel := GetElementNativeValues(e, 'Male world model\MOD2');
|
||||
if ElementExists(e,'Female world model\MOD3') then femaleModel := GetElementNativeValues(e, 'Female world model\MOD3');
|
||||
if ElementExists(e,'Male 1st Person\MOD4') then maleModel1st := GetElementNativeValues(e, 'Male 1st Person\MOD4');
|
||||
if ElementExists(e,'Female 1st Person\MOD5') then femaleModel1st := GetElementNativeValues(e, 'Female 1st Person\MOD5');
|
||||
if RetrieveAddRaces and ElementExists(e,'Additional Races') then
|
||||
begin
|
||||
elRaces := ElementByName(e, 'Additional Races');
|
||||
for i := 0 to ElementCount(elRaces) - 1 do begin
|
||||
additionalRaces := additionalRaces + GetElementEditValues(LinksTo(ElementByIndex(elRaces,i)), 'EDID');
|
||||
if(i < (ElementCount(elRaces) - 1)) then additionalRaces := additionalRaces + ',';
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if Signature(e) = 'ARMO' then
|
||||
begin
|
||||
if ElementExists(e,'Male world model\MOD2') then maleModel := GetElementNativeValues(e, 'Male world model\MOD2');
|
||||
if ElementExists(e,'Female world model\MOD4') then femaleModel := GetElementNativeValues(e, 'Female world model\MOD4');
|
||||
if ElementExists(e,'KWDA') then
|
||||
begin
|
||||
elKwda := ElementBySignature(e, 'KWDA');
|
||||
for i := 0 to ElementCount(elKwda) - 1 do begin
|
||||
keywords := keywords + GetElementEditValues(LinksTo(ElementByIndex(elKwda,i)), 'EDID');
|
||||
if(i < (ElementCount(elKwda) - 1)) then keywords := keywords + ',';
|
||||
end;
|
||||
end;
|
||||
if ElementExists(e,'Armature') then
|
||||
begin
|
||||
|
||||
elArma := ElementByName(e, 'Armature');
|
||||
for i := 0 to ElementCount(elArma) - 1 do begin
|
||||
armature := armature + GetElementEditValues(LinksTo(ElementByIndex(elArma,i)), 'EDID');
|
||||
if(i < (ElementCount(elArma) - 1)) then armature := armature + ',';
|
||||
end;
|
||||
end;
|
||||
end
|
||||
end;
|
||||
|
||||
//loop through the 32 slots
|
||||
i := 1;
|
||||
while(i <= 32) do
|
||||
begin
|
||||
i := i + 1;
|
||||
//bitwise and
|
||||
if ((slot and 1) = 1) then
|
||||
begin
|
||||
slotList.Add(IntToStr(i+28));
|
||||
AddMessage(espName + ';' + Signature(e) + ';' + formId +';'+ GetElementEditValues(e, 'EDID') + ';' + itemName + ';' + maleModel + ';' + femaleModel +';' + armorType +';' + enchantment + ';' + FloatToStr(rating/100) + ';' + FloatToStr(weight) + ';' + IntToStr(value) + ';' + IntToStr(i+28) + ';' + keywords);
|
||||
if Signature(e) = 'ARMO' then
|
||||
ArmoListSlot.Add(espName + ';'
|
||||
+ Signature(e) + ';'
|
||||
+ formId + ';'
|
||||
+ GetElementEditValues(e, 'EDID') + ';'
|
||||
+ IntToStr(i+28) + ';'
|
||||
+ primaryRace + ';'
|
||||
+ itemName + ';'
|
||||
+ maleModel + ';'
|
||||
+ femaleModel +';'
|
||||
+ armorType +';'
|
||||
+ enchantment + ';'
|
||||
+ FloatToStr(rating/100) + ';'
|
||||
+ FloatToStr(weight) + ';'
|
||||
+ IntToStr(value) + ';'
|
||||
+ keywords + ';'
|
||||
+ armature
|
||||
);
|
||||
if Signature(e) = 'ARMA' then
|
||||
ArmaListSlot.Add(espName + ';'
|
||||
+ Signature(e) + ';'
|
||||
+ formId + ';'
|
||||
+ GetElementEditValues(e, 'EDID') + ';'
|
||||
+ IntToStr(i+28) + ';'
|
||||
+ primaryRace + ';'
|
||||
+ maleModel + ';'
|
||||
+ femaleModel +';'
|
||||
+ maleModel1st + ';'
|
||||
+ femaleModel1st + ';'
|
||||
+ additionalRaces
|
||||
);
|
||||
end
|
||||
slot := slot shr 1;
|
||||
end;
|
||||
|
||||
if Signature(e) = 'ARMO' then
|
||||
ArmoList.Add(espName + ';'
|
||||
+ Signature(e) + ';'
|
||||
+ formId + ';'
|
||||
+ GetElementEditValues(e, 'EDID') + ';'
|
||||
+ slotList.DelimitedText + ';'
|
||||
+ primaryRace + ';'
|
||||
+ itemName + ';'
|
||||
+ maleModel + ';'
|
||||
+ femaleModel +';'
|
||||
+ armorType +';'
|
||||
+ enchantment + ';'
|
||||
+ FloatToStr(rating/100) + ';'
|
||||
+ FloatToStr(weight) + ';'
|
||||
+ IntToStr(value) + ';'
|
||||
+ keywords + ';'
|
||||
+ armature
|
||||
);
|
||||
if Signature(e) = 'ARMA' then
|
||||
ArmaList.Add(espName + ';'
|
||||
+ Signature(e) + ';'
|
||||
+ formId + ';'
|
||||
+ GetElementEditValues(e, 'EDID') + ';'
|
||||
+ slotList.DelimitedText + ';'
|
||||
+ primaryRace + ';'
|
||||
+ maleModel + ';'
|
||||
+ femaleModel +';'
|
||||
+ maleModel1st + ';'
|
||||
+ femaleModel1st + ';'
|
||||
+ additionalRaces
|
||||
);
|
||||
slotList.Free;
|
||||
end;
|
||||
|
||||
// Called after the script has finished processing every record
|
||||
function Finalize : integer;
|
||||
var filenameArmo : string;
|
||||
var filenameArma : string;
|
||||
var filenameArmoSlot : string;
|
||||
var filenameArmaSlot : string;
|
||||
begin
|
||||
filenameArmo := ProgramPath + 'ArmorExport-Armor.csv';
|
||||
filenameArma := ProgramPath + 'ArmorExport-ArmorAddon.csv';
|
||||
filenameArmoSlot := ProgramPath + 'ArmorExport-Armor-Slot.csv';
|
||||
filenameArmaSlot := ProgramPath + 'ArmorExport-ArmorAddon-Slot.csv';
|
||||
|
||||
AddMessage('Saving Armor list to ' + filenameArmo);
|
||||
AddMessage('Saving ArmorAddon list to ' + filenameArma);
|
||||
AddMessage('Saving Armor-Slot list to ' + filenameArmoSlot);
|
||||
AddMessage('Saving ArmorAddon-Slot list to ' + filenameArmaSlot);
|
||||
ArmoList.SaveToFile(filenameArmo);
|
||||
ArmoList.Free;
|
||||
ArmaList.SaveToFile(filenameArma);
|
||||
ArmaList.Free;
|
||||
ArmoListSlot.SaveToFile(filenameArmoSlot);
|
||||
ArmoListSlot.Free;
|
||||
ArmaListSlot.SaveToFile(filenameArmaSlot);
|
||||
ArmaListSlot.Free;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -0,0 +1,6 @@
|
||||
param([Parameter(Mandatory=$true)][string[]]$keyword)
|
||||
### keyword to filter
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';' `
|
||||
|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ } `
|
||||
|where-object { $keyword -in $_.Keywords }
|
||||
@@ -0,0 +1,4 @@
|
||||
param([Parameter(Mandatory=$true)][int]$slot)
|
||||
#slot to filter
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-Armor-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Where-Object { $_.Slot -eq $slot }
|
||||
@@ -0,0 +1,2 @@
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';'|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ }|where-object { $_.Keywords -contains 'ArmorHeavy' }
|
||||
@@ -0,0 +1,2 @@
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-Armor.csv|convertFrom-Csv -Delimiter ';'|ForEach-Object { $_.Keywords = ($_.Keywords -split ','); $_ }|where-object { $_.Keywords -contains 'ArmorLight' }
|
||||
@@ -0,0 +1,3 @@
|
||||
#show count of records by slot
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-Armor-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Sort-Object Slot|Group-Object -NoElement -Property slot
|
||||
@@ -0,0 +1,3 @@
|
||||
param([Parameter(Mandatory=$true)][int]$slot)
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-ArmorAddon-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Where-Object { $_.Slot -eq $slot }
|
||||
@@ -0,0 +1,3 @@
|
||||
#show count of records by slot
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
Get-Content $csvDir\ArmorExport-ArmorAddon-Slot.csv|ConvertFrom-Csv -Delimiter ';'|Sort-Object -Property FormID,Slot -Unique|Sort-Object Slot|Group-Object -NoElement -Property slot
|
||||
@@ -0,0 +1,51 @@
|
||||
<#
|
||||
.PARAMETER editorId
|
||||
to filter by editorId
|
||||
|
||||
.PARAMETER formId
|
||||
to filter by formId
|
||||
|
||||
.PARAMETER all
|
||||
to list all records
|
||||
|
||||
.PARAMETER slotAsArray
|
||||
convert slot field to array
|
||||
|
||||
.PARAMETER splitBySlot
|
||||
split records by slot
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\get-armor.ps1 -formId 000B9745
|
||||
#>
|
||||
param([string]$editorId, [string]$formId, [switch]$slotAsArray, [switch]$splitBySlot)
|
||||
#editorId or formId to filter
|
||||
|
||||
#usage:
|
||||
## .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03
|
||||
## .\get-armor.ps1 -formId 000B9745
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
$csvFile="ArmorExport-Armor.csv"
|
||||
if($splitBySlot) {
|
||||
$csvFile="ArmorExport-Armor-Slot.csv"
|
||||
}
|
||||
if($editorId -or $formId) {
|
||||
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|
||||
|where-object { ($editorId -and $_.EditorID -eq $editorId) -or ($formId -and $_.FormID -eq $formId)} `
|
||||
|foreach-object {
|
||||
$_.Keywords = $_.Keywords -Split ',';
|
||||
$_.ArmorAddon = $_.ArmorAddon -Split ',';
|
||||
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); }
|
||||
$_
|
||||
}
|
||||
} else {
|
||||
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|
||||
|foreach-object {
|
||||
$_.Keywords = $_.Keywords -Split ',';
|
||||
$_.ArmorAddon = $_.ArmorAddon -Split ',';
|
||||
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); }
|
||||
$_
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<#
|
||||
.PARAMETER editorId
|
||||
to filter by editorId
|
||||
|
||||
.PARAMETER formId
|
||||
to filter by formId
|
||||
|
||||
.PARAMETER all
|
||||
to list all records
|
||||
|
||||
.PARAMETER slotAsArray
|
||||
convert slot field to array
|
||||
|
||||
.PARAMETER splitBySlot
|
||||
split records by slot
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\get-armor.ps1 | ?{ $_.FormID -in '00013939' } | .\get-armoraddon.ps1
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\get-armoraddon.ps1 -formId 0005DB82
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03|.\get-armoraddon.ps1
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\armor-by-keyword.ps1 ArmorHeavy|?{$_.Keywords -contains 'ArmorHelmet'}|.\get-armoraddon.ps1
|
||||
#>
|
||||
param([string]$editorId, [string]$formId, [switch]$all, [switch]$slotAsArray, [switch]$splitBySlot)
|
||||
# editorId or formId to filter
|
||||
# -all to list all records
|
||||
|
||||
#usage:
|
||||
## .\get-armor.ps1 | ?{ $_.FormID -in '00013939' } | .\get-armoraddon.ps1
|
||||
## .\get-armoraddon.ps1 -formId 0005DB82
|
||||
## .\get-armor.ps1 -editorId EnchArmorImperialLightGauntletsMarksman03|.\get-armoraddon.ps1
|
||||
## .\armor-by-keyword.ps1 ArmorHeavy|?{$_.Keywords -contains 'ArmorHelmet'}|.\get-armoraddon.ps1
|
||||
|
||||
Set-StrictMode -Version 3.0
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
|
||||
$myInput = $input
|
||||
|
||||
$ids=@()
|
||||
|
||||
$inObjs=@{}
|
||||
foreach($i in $myInput) {
|
||||
foreach($a in $i.ArmorAddon) {
|
||||
$ids+=$a;
|
||||
if($inObjs.ContainsKey($a)) {
|
||||
$inObjs[$a]=$i
|
||||
} else {
|
||||
$inObjs.Add($a, $i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$csvDir=(Join-Path $PSScriptRoot ..)
|
||||
$csvFile="ArmorExport-ArmorAddon.csv"
|
||||
if($splitBySlot) {
|
||||
$csvFile="ArmorExport-ArmorAddon-Slot.csv"
|
||||
}
|
||||
|
||||
if($editorId -or $formId) {
|
||||
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|
||||
|where-object { ($editorId -and $_.EditorID -eq $editorId) -or ($formId -and $_.FormID -eq $formId)} `
|
||||
|foreach-object { `
|
||||
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
|
||||
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
|
||||
$_ `
|
||||
}
|
||||
} elseif($ids.Length -gt 0) {
|
||||
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|
||||
|where-object { $ids -contains $_.EditorID } `
|
||||
|foreach-object { `
|
||||
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
|
||||
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
|
||||
$_ } `
|
||||
|foreach-object { Add-Member -InputObject $_ -MemberType NoteProperty -Name _ArmoRef `
|
||||
-Value "$($inObjs[$_.EditorID].EditorID) `"$($inObjs[$_.EditorID].Name)`" [$($inObjs[$_.EditorID].RecordType):$($inObjs[$_.EditorID].FormID)]"; `
|
||||
$_ }
|
||||
} elseif($all) {
|
||||
Get-Content (Join-Path $csvDir $csvFile)|ConvertFrom-Csv -Delimiter ';' `
|
||||
|foreach-object { `
|
||||
if($slotAsArray -and !$splitBySlot) { $_.Slot = ($_.Slot -Split ','); } `
|
||||
$_.AdditionalRaces = ($_.AdditionalRaces -Split ','); `
|
||||
$_ }
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
traits: direct - boisterous - patriarchal - revanchist - warm to kin, wary of outsiders
|
||||
traits: direct - boisterous - patriarchal - revanchist - warm to kin, openly racist to outsiders
|
||||
|
||||
Reference in New Issue
Block a user