Companion Dogs: คู่มือการม็อด
วิธีสร้างส่วนเสริมของคุณเอง สายพันธุ์ใหม่ หรือสัตว์ชนิดใหม่ทั้งชนิด ในรูปม็อดแยกบน Workshop ที่เสียบเข้ากับ Companion Dogs
คู่มือเล่มนี้สำหรับคนที่เขียนม็อด ถ้าคุณแค่อยากเล่น ให้อ่านอีกสองเล่มแทน ฟีเจอร์ สำหรับสิ่งที่สุนัขทำได้ และ สายพันธุ์ สำหรับสายพันธุ์
คู่มือนี้ถือว่าคุณอ่าน Lua ได้ และมีโมเดลที่ริกและใส่แอนิเมชันไว้แล้วสำหรับสัตว์ของคุณ สายงานศิลป์ไม่ได้อยู่ในนี้ หัวข้อ 2 ระบุว่าไฟล์โมเดลต้องผ่านเงื่อนไขอะไรบ้าง
ทุกอย่างที่คู่มือนี้เอ่ยชื่อไว้เป็นสัญญาสาธารณะ และมีไว้ให้เรียกจากนอกม็อด สิ่งที่ไม่ได้เอ่ยชื่อไว้ที่นี่เป็นของภายใน และเปลี่ยนได้ในเวอร์ชันไหนก็ได้โดยไม่แจ้งล่วงหน้า
1. ส่วนเสริมคืออะไร
ส่วนเสริมคือม็อด Workshop ธรรมดาที่ประกาศ require=CompanionDogs แล้วเรียกฟังก์ชันหนึ่งตัวตอนโหลด มันเพิ่มสายพันธุ์เดียว (หรือหลายสายพันธุ์ ถ้าใช้ร่างเดียวกัน) และไม่มีอย่างอื่น
ม็อดฐานเป็นเจ้าของ
- เครื่องสถานะของแอนิเมชัน ชุดแอนิเมชัน และโครงกระดูก
- การเดินตาม การหาเส้นทาง การต่อสู้ การล่า การต้อนปศุสัตว์ การเฝ้าระวัง ความต้องการ และการดูแลประจำวัน
- อินเทอร์เฟซทั้งหมด หน้าต่างสุนัข เมนูวงกลม เมนูคลิกขวา คอกสุนัข หมุดบนแผนที่
- การทำให้เชื่อง ความผูกพัน การผสมพันธุ์ ลูกสุนัข และลูกผสม
- ตัวเลือกแซนด์บ็อกซ์ และการซิงก์ในมัลติเพลเยอร์
ส่วนเสริมของคุณเป็นเจ้าของ
- ตัวเลขที่ทำให้สัตว์ของคุณต่างจาก Caramelo
- โมเดลร่างกาย เท็กซ์เจอร์ ภาพเหมือน และไอคอน moodle ถ้ามี
- ว่าจะเจอมันที่ไหนในโลก
- ชื่อและคำบรรยาย ในทุกภาษาที่คุณแนบไปด้วย
สองสีที่ประพฤติเหมือนกัน สำหรับฐานก็ยังเป็นสองสายพันธุ์ (สองชื่อ สองรายการในคอก) คุณเขียนมันขึ้นจาก ตารางที่ใช้ร่วมกันตัวเดียว แบบเดียวกับที่ CD: Cats ทำกับขนทั้งห้าแบบ
2. สิ่งที่ต้องมีก่อนเริ่ม
สัตว์ของคุณต้องมี .glb แบบสกินของตัวเองอยู่ใต้ media/models_X/Skinned/ พร้อมคลิปแอนิเมชัน Rac_* ครบทั้ง 21 คลิป คลิปไม่ถูกสืบทอดข้ามไฟล์โมเดล โมเดลที่มีสิบห้าคลิปให้สัตว์ที่ค้างแข็งทันทีที่ถูกขอคลิปใดคลิปหนึ่ง ในหกคลิปที่เหลือ โมเดลยังต้องมีกระดูกไม่เกิน 60 ชิ้น และมีโนดบนสุดอยู่ที่เอกลักษณ์ ไม่อย่างนั้นเอนจินจะโยน ข้อผิดพลาดทุกเฟรมและสัตว์จะเรนเดอร์ออกมาเป็นรอยเปื้อนดำ อีกสองคลิปเป็นทางเลือก Rac_WalkLimpFront และ Rac_WalkLimpBack (วงจรเดินขากะเผลก) ทั้งคู่มีผลก็ต่อเมื่อคุณตั้ง limpAnim = true ในนิยามสายพันธุ์
ถ้าคุณยังไม่มีโมเดล คุณเขียนและทดสอบทุกอย่างที่เหลือได้ด้วยการชี้ CD.applyDogModel ไปที่ร่างของฐานตัวใดตัวหนึ่ง สัตว์จะหน้าตาเหมือน Caramelo แต่ทุกระบบในคู่มือนี้ทำงานครบ
คุณยังต้องมีเท็กซ์เจอร์สำหรับร่างกาย และภาพเหมือนสำหรับหน้าต่างคอก
ตัดสินใจก่อนเขียนโค้ดว่าสัตว์ของคุณเป็นสายพันธุ์หรือเป็นสปีชีส์ สายพันธุ์คือสุนัขที่มีตัวเลขต่างออกไป ส่วนสปีชีส์คือสัตว์ที่ไม่มีงานบางอย่างเลย ตัวเลือกนี้เปลี่ยนว่าคุณต้องเขียนฟิลด์ไหนบ้าง หัวข้อ 6 ว่าด้วยเรื่องนี้
3. ไฟล์ของส่วนเสริม
นี่คือ CD: Pug ซึ่งเป็นส่วนเสริมที่เล็กที่สุดที่เผยแพร่แล้ว พร้อมส่วนที่สำคัญ
CompanionDogsPug/
42/
mod.info
icon.png
poster.png
media/
models_X/Skinned/Pug_Body.glb
scripts/models_pug.txt
textures/Body/Pug.png
textures/CDPortrait_pug.png
lua/shared/CompanionDogsPug_Breed.lua
lua/shared/Definitions/animal/PugDefinitions.lua
lua/shared/Definitions/animal/CompanionDogsPug_Parts.lua
lua/client/CompanionDogsPug_Moodle.lua
lua/shared/Translate/EN/IG_UI.json
lua/shared/Translate/PTBR/IG_UI.json
common/
และ mod.info
id=CompanionDogsPug
name=CD: Pug
description=Pugs for Companion Dogs. REQUIRES the Companion Dogs mod (0.6.8 or newer).
poster=poster.png
icon=icon.png
require=CompanionDogs
modversion=0.1.0
pzversion=42.19.0
versionMin=42.18.0
require=CompanionDogs คือบรรทัดที่สำคัญ มันรับประกันว่า Lua ของฐานทั้งหมดรันจบก่อนของคุณทุกเฟส shared ก่อน แล้ว client แล้ว server ถ้าไม่มีบรรทัดนี้ ไฟล์ของคุณอาจโหลดก่อน และทุกการเรียก CD. จะเป็นการอ้างดัชนีบน nil
versionMin บอกว่า "ต้องใช้ Companion Dogs 0.6.8" ไม่ได้ ฟิลด์นั้นกั้นได้แค่บิลด์ของเกม และไม่มีฟิลด์ใน mod.info สำหรับเวอร์ชันของสิ่งที่ต้องพึ่งพา พื้นขั้นต่ำของฐานถูกบังคับด้วยด่านตรวจในหัวข้อถัดไป และประกาศให้ ผู้เล่นรู้ผ่านคำบรรยายของคุณ เขียนไว้ตรงนั้นเป็นคำพูด ไม่อย่างนั้นอาการเดียวที่ผู้เล่นได้คือสัตว์ที่ไม่เคยโผล่มาเลย
4. ด่านตรวจเวอร์ชัน
วางบรรทัดนี้ไว้บนสุดของไฟล์ Lua ทุกไฟล์ของส่วนเสริม พร้อมเลขที่ส่วนเสริมของคุณต้องใช้
local CD = CompanionDogs
if not (CD and CD.registerBreed and (CD.API_VERSION or 0) >= 3) then return end
ถ้าไม่มีฐานหรือฐานเก่าเกินไป ไฟล์จะคืนค่าตั้งแต่บรรทัดที่สอง และส่วนเสริมจะไม่ทำอะไรเลย ไม่มีสายพันธุ์ ไม่มีการเกิด ไม่มี moodle ไม่มีบรรทัดในล็อก
ด่านตรวจเป็นของแต่ละไฟล์ และแต่ละไฟล์ตรวจตามสิ่งที่ตัวเองใช้ PugDefinitions.lua ต้องใช้เฮลเปอร์ของโมเดล มันจึงตรวจสิ่งเหล่านั้น
if not (CompanionDogs and CompanionDogs.applyDogModel and CompanionDogs.DOG_SOUNDS) then return end
อย่าสร้างตัวแปรโกลบอลขึ้นมาเอง CompanionDogs = CompanionDogs or {} ในส่วนเสริมเปลี่ยนฐานที่หายไป ให้กลายเป็นตารางที่สร้างไว้ครึ่งเดียว และด่านตรวจทุกด่านที่อยู่ถัดไปก็จะผ่านทั้งที่ไม่ควรผ่าน
5. การลงทะเบียนสายพันธุ์
เรียกครั้งเดียว ในไฟล์ shared
CD.registerBreed({
key = "pug",
engineBreed = "pug",
typePrefix = "pug",
nameKey = "IGUI_PD_Breed_pug",
litter = { 1, 2 },
xpMult = { scent = 1.5, combat = 1, obedience = 2.0, hunt = 1.2, herding = 1.0 },
combatPower = 0.15,
lethalityCurve = { min = 0.40, max = 1.3 },
canKill = false,
canKnockdown = false,
combatStressMult = 0.9,
panicThreshold = 0.70,
bagMult = 0.6,
sentinelMult = 1.35,
barkNoiseMult = 1.5,
alertModeLocked = true,
loyaltyDecayMult = 0,
geneRange = {
strength = { 0.00, 0.10 },
aggressiveness = { 0.05, 0.20 },
resistance = { 0.00, 0.15 },
stress = { 0.55, 0.85 },
},
spawns = {
{ id = "pughouse", class = "house", suffix = "|pg", breed = "pug",
chance = function() return CD.strayChancePerHouse() / CD.PUG_HOUSE_RARITY end },
},
})
การเรียกครั้งนี้แทรกสายพันธุ์เข้าไป ลงทะเบียนชนิดสัตว์ทั้งสามของมัน สร้างลำดับการผสมพันธุ์ใหม่เพื่อให้สัตว์ของคุณ เข้าร่วมการผสมข้ามสายพันธุ์ และลงทะเบียนขั้นตอนการเกิด
นิยามที่ไม่ถูกต้องทำให้การเรียกคืนค่า nil แทนที่จะโยนข้อผิดพลาด การโหลดจึงเดินต่อ การปฏิเสธแต่ละครั้ง พิมพ์บรรทัดที่ระบุชื่อลงในล็อก
ฟิลด์ที่ต้องมี
| ฟิลด์ | มันคืออะไร |
|---|---|
key |
ตัวระบุสายพันธุ์ของคุณ ต้องไม่ซ้ำกับม็อดใดในโลก อย่าเปลี่ยนมันหลังปล่อยแล้ว |
typePrefix |
คำนำหน้าของชนิดสัตว์ทั้งสาม <prefix>pup <prefix>female <prefix>male เป็นตัวเลือกเมชของร่างกาย |
nameKey |
คีย์การแปลของชื่อที่แสดง |
xpMult |
ความเร็วการเรียนรู้ต่อทักษะ scent combat obedience hunt herding โดย 1.0 คือปกติ |
combatPower |
มันตีแรงแค่ไหน Caramelo อยู่ที่ 0.20 ส่วนสายพันธุ์นักสู้อยู่เหนือ 1.0 |
lethalityCurve |
{ min, max } ความเสียหายโตอย่างไรจาก Combat 0 ถึง Combat 10 |
geneRange |
ช่วงตอนเกิดของยีนทั้งสี่ strength aggressiveness resistance stress แต่ละตัวเป็น { low, high } ภายใน 0 ถึง 1 |
ฟิลด์ที่จะใส่หรือไม่ใส่ก็ได้
| ฟิลด์ | ค่าเริ่มต้น | มันทำอะไร |
|---|---|---|
engineBreed |
ตาม key |
ชื่อสายพันธุ์ที่ส่งให้เอนจิน มันเลือกเท็กซ์เจอร์ ห้ามซ้ำระหว่างสายพันธุ์ |
descKey |
IGUI_PD_BreedDesc_<key> |
คีย์คำบรรยาย หลายสายพันธุ์ใช้คีย์เดียวกันได้ |
litter |
ค่าของฐาน | { min, max } จำนวนลูกต่อการคลอดหนึ่งครั้ง |
canKill |
true | false แปลว่ามันบั่นทอนซอมบี้ได้ แต่ไม่เคยลงหมัดสังหาร |
canKnockdown |
false | true ให้มันผลักซอมบี้ล้มได้ |
combatStressMult |
1 | การสู้หนึ่งครั้งทำให้มันเครียดแค่ไหน |
panicThreshold |
ค่าของฐาน | ระดับความเครียดที่ทำให้มันเลิกสู้ panicImmune = true แปลว่ามันไม่เลิกเลย |
bagMult |
1 | ตัวคูณความจุของกระเป๋าอาน |
puppySize |
0.6 | สเกลภาพของลูกสัตว์แบบสัมบูรณ์ สายพันธุ์เล็กต้องตั้งค่านี้ ไม่อย่างนั้นลูกจะเกิดมาตัวเท่าตัวเต็มวัย |
sentinelMult |
1 | คูณรัศมีการเฝ้าระวังสุดท้าย |
barkNoiseMult |
1 | ปรับรัศมีและความดังของเสียงเห่าเตือน ถ้าปิดตัวเลือกเสียงในแซนด์บ็อกซ์ ไม่มีสายพันธุ์ไหนดึงซอมบี้ด้วยเสียงเห่าได้ ไม่ว่าค่าจะเป็นเท่าไร |
loyaltyDecayMult |
1 | คูณอัตราที่ความซื่อสัตย์ลดลงต่อวัน 0 แปลว่าความผูกพันไม่จางเลย |
alertModeLocked |
false | สัตว์อยู่ในโหมดเฝ้าระวังเต็มที่ตลอด เจ้าของตั้งเป็นเงียบหรือเงียบสนิทที่ไหนไม่ได้เลย |
huntFetchLevel |
6 | ระดับ Hunt ที่มันเริ่มคาบเหยื่อกลับมาให้เจ้าของ |
huntDeliverTimeoutMin |
5 | นาทีในเกมที่มันพยายามส่งเหยื่อก่อนจะยอมแพ้ |
distract |
ปิด | { <kind> = { chance = 0..1, ... } } สายพันธุ์นี้ไล่ตามสิ่งต่าง ๆ ด้วยตัวเอง โดยไม่ต้องมีโหมดและไม่ต้องมีระดับ |
idleAnimMs |
ค่าของฐาน | ความยาวของช่วงแอนิเมชันตอนอยู่เฉย เป็นมิลลิวินาที ตั้งค่านี้เมื่อคลิปของคุณสั้นกว่าของสุนัข ไม่อย่างนั้นลูปจะเริ่มใหม่และตัดท่ากลางคัน |
restAnim |
true | false ทำให้สัตว์ยืนอยู่ตอน Stay และ Guard แทนที่จะหมอบลง |
restPoses |
หมอบลง | รายการท่าพักที่สัตว์สุ่มหยิบทุกครั้งที่มันลงนอน จะใส่ท่าเปลี่ยนเข้าออกและท่าแปรผันตอนอยู่เฉยเพิ่มก็ได้ ต้องมีคลิปและโหนดแอนิเมชันของคุณเอง |
limpAnim |
false | true ทำให้สัตว์ที่บาดเจ็บเดินกะเผลก ตั้งค่านี้เฉพาะเมื่อโมเดลของคุณมีคลิปทางเลือกสองคลิปคือ Rac_WalkLimpFront และ Rac_WalkLimpBack (วงจรเดิน 1.0 วินาที ที่มี root motion เท่ากับ Rac_Walk) ถ้าไม่มีคลิป สัตว์จะเดินค้างอยู่กับที่ |
bandSkin |
ปิด | { base, front, back, cutFront, cutBack } ชื่อเท็กซ์เจอร์ลำตัวห้าชื่อ ที่ขาข้างที่บาดเจ็บ สัตว์จะใส่แบบมีรอยแผลขณะที่แผลยังมีเลือดออก และแบบพันผ้าขณะที่พันแผลไว้ สร้างทั้งสี่แบบด้วย _dogrig/forge/_paw_band.py ถ้าไม่ตั้งค่านี้ สัตว์ก็ยังบาดเจ็บได้ตามปกติ แค่ไม่มีรอยให้เห็น |
voices |
เสียงของสุนัข | { bark, growl, idle, wildbark, pet, whine, eat, drink } |
diet |
รายการของสุนัข | สิ่งที่สัตว์ห้ามกิน สิ่งที่นับเป็นเนื้อสำหรับมัน และสิ่งที่มันกินเองจากรางอาหาร |
maleChance |
0.5 | สัดส่วนที่เกิดเป็นตัวผู้ ตั้งแต่ 0 ถึง 1 |
sterileMale |
false | true กันตัวผู้ของสายพันธุ์นั้นออกจากการผสมพันธุ์ |
species |
"dog" |
การผสมพันธุ์ถูกปิดตามสปีชีส์ ดูหัวข้อ 6 |
skills, canBreed, huntMaxPrey |
เปิดทุกอย่าง | บล็อกเชิงโครงสร้าง ดูหัวข้อ 6 |
ตัวเลขและแฟล็กที่คุณเพิ่มลงในนิยามอ่านกลับได้ด้วย CD.breedNumber(animal, field) และ CD.breedFlag(animal, field) ไม่ใช่ด้วย CD.getBreedDef(animal).field สองตัวนี้รับมือกับฟิลด์ที่หายไปได้ และยังทำงานต่อเมื่อฐานเปลี่ยน
สัญชาตญาณ distract
distract = {
prey = { chance = 0.25 },
},
สายพันธุ์ที่ประกาศฟิลด์นี้จะสังเกตเห็นอะไรบางอย่างเป็นครั้งคราวแล้วไล่ตามมันไป โดยทิ้งสิ่งที่กำลังทำอยู่ มันทำแบบนี้ทั้งตอน Stay และตอน Follow ระหว่างนั้นคำสั่งจะถูกปฏิเสธกลับมาพร้อมข้อความ distracted ตัวเดียวกับที่การทอยความเชื่อฟังใช้อยู่แล้ว Come เป็นคำสั่งเดียวที่ผ่านเข้าไปได้ และมันยกเลิกการวอกแวก
ทุกชนิดรับปุ่มปรับชุดเดียวกัน สิ่งที่คุณไม่ได้ใส่จะใช้ค่าเริ่มต้นของม็อด
| ฟิลด์ | มันทำอะไร |
|---|---|
chance |
0..1 ทอยก็ต่อเมื่อทริกเกอร์ของชนิดนั้นเจอบางอย่างแล้ว การเขียน 25 เพื่อหมายถึง "25%" จะถูกปฏิเสธพร้อมบรรทัดที่ระบุชื่อในล็อก |
radius |
จำนวนช่องที่ทริกเกอร์ค้นหา ในกรณีที่ชนิดนั้นมีการค้นหา |
durationMin |
นาทีในเกมที่ช่วงวอกแวกอยู่ได้ก่อนจะหมดอายุเอง |
cooldownMin |
นาทีในเกมก่อนที่สัตว์ตัวเดิมจะวอกแวกได้อีกครั้ง |
ชนิด prey
ชนิดเดียวที่ม็อดฐานแถมมาให้ สัตว์จะไล่ตามสัตว์ป่า และ classes เป็นตัวเลือกว่าตัวไหนนับบ้าง
distract = {
prey = { chance = 0.25, radius = 6, classes = { tiny = true, small = true } },
},
มีข้อจำกัดสองข้อที่บังคับเสมอ ไม่ว่าคุณจะประกาศอะไร
- มันไม่เคยเกิน
huntMaxPreyของคุณ สายพันธุ์ที่ถูกจำกัดไว้ที่smallจะไม่ไล่กวางแม้จะประกาศlargeไว้ - ประตูระดับถูกข้ามเฉพาะกับ
tinyสัตว์ที่เพิ่งเชื่องและมี Hunt 0 ก็จับหนูได้แล้ว ถ้าประกาศsmallไว้ สายพันธุ์นั้นจะไล่กระต่ายที่ระดับใดก็ได้ แต่การฆ่ายังต้องใช้ระดับ Hunt เท่าที่ Labrador ต้องใช้
ตัวเลือกการล่าในแซนด์บ็อกซ์มีผลกับการฆ่าเท่านั้น สัตว์ยังไล่ตามอยู่ แต่เหยื่อจะหนีรอดไป
เหยื่อที่ตายด้วยวิธีนี้เข้าสู่การเก็บกลับตามปกติ huntFetchLevel ของสายพันธุ์คุณจึงเป็นตัวตัดสินว่ามันจะคาบซาก กลับมาให้เจ้าของหรือไม่ ที่ 0 สัตว์ส่งของให้ตั้งแต่วันแรก ซึ่งเป็นวิธีที่แมวคาบหนูตายมาให้คุณ การส่งของอยู่ได้ นานกว่าช่วงวอกแวก เมื่อเหยื่อตายแล้วสัตว์ก็รับคำสั่งได้อีก และการเดินทางกลับบ้านใช้ huntDeliverTimeoutMin ของตัวมันเอง
การเขียนชนิดของคุณเอง
distract เป็นตัวกระจายงาน ลงทะเบียนของคุณเองแบบนี้
CD.registerDistraction("butterfly", {
gate = function(animal, cfg) return animal:isOutside() end, -- optional, cheap pre-check
find = function(animal, cfg) return findButterflyNear(animal, cfg.radius) end,
drive = function(animal, owner, d, cfg) return chaseIt(animal, d) end,
stop = function(animal, d) end, -- optional, cleanup
})
จากนั้นประกาศมันบนสายพันธุ์เหมือนชนิดอื่น distract = { butterfly = { chance = 0.10 } }
gate รันก่อนงบการสแกนรวมของม็อด find รันหลังงบนั้นและเป็นตัวค้นหาที่แพง drive คืนค่า true ตราบใดที่ มันยังขับสัตว์อยู่ และคืนค่า false เมื่อจบ ซึ่งเป็นการปิดช่วงวอกแวก ตัวจัดการของคุณรันอยู่ใน pcall ของตัวเอง ถ้ามันโยนข้อผิดพลาด ม็อดจะบันทึกบรรทัดที่ระบุชื่อ ถอนทะเบียนชนิดนั้นสำหรับเซสชันนี้ และปล่อยให้ส่วนที่เหลือ ของเพื่อนร่วมทางทำงานต่อ
ชื่อที่สงวนไว้ให้ชนิดของฐานในอนาคต drink eat play วันนี้คุณลงทะเบียนชนิดใต้ชื่อเหล่านั้นได้ แต่ฐานจะยึด ชื่อคืนเมื่อมันปล่อยของตัวเองออกมา
ท่าพัก
สัตว์ที่พักจะหมอบลง restPoses แทนที่ท่าเดียวนั้นด้วยรายการที่สัตว์สุ่มหยิบทุกครั้งที่มันลงนอน:
restPoses = {
"cdRest", -- the base lie-down
{ var = "cdSit", enter = "cdSitIn", exit = "cdSitOut",
variation = { "cdSitGroom", "cdSitGroom2" } },
},
แต่ละรายการเป็นชื่อตัวแปรแอนิเมชันหรือเป็นตาราง var คือบูลีนที่เปิดค้างไว้ตลอดช่วงพัก enter กับ exit คือพัลส์ที่เล่นครั้งเดียวตอนลงนอนและตอนลุกขึ้น variation คือรายการพัลส์เล่นครั้งเดียวที่มันเล่นเป็นครั้งคราวระหว่างค้างท่า ตามนาฬิกาเดียวกับท่าแปรผันตอนอยู่เฉย มีแค่ var เท่านั้นที่บังคับ
การสุ่มเป็นแบบเท่ากันและเกิดทุกครั้งที่เข้าสู่การพัก ดังนั้นสองรายการก็คือ 50% ต่อรายการ และสัตว์อาจสุ่มได้ท่าเดิมสองครั้งติดกัน มันไม่ใช่การสลับกัน
พัลส์แต่ละอันยาวเท่าที่ idleAnimMs กำหนดให้ตัวแปรนั้น ดังนั้นให้ส่งเป็นรูปแบบตารางและกำหนดความยาวให้ทุกตัวแปร รวมถึงตัวแปรตอนอยู่เฉยที่คุณมีอยู่แล้วด้วย ใส่ ความยาวจริงของคลิป
idleAnimMs = { cdIdle2 = 3800, cdIdle3 = 3800, cdSitIn = 1375, cdSitOut = 1417,
cdSitGroom = 19833, cdSitGroom2 = 25167 },
คลิปและโหนดเป็นของคุณ ไม่ใช่ของฐาน ตัวแปรแต่ละตัวต้องมีไฟล์โหนดในส่วนเสริมของคุณใต้ media/AnimSets/raccoon/idle/ และคลิปที่ m_AnimName ของมันชี้ไปต้องมีอยู่ในโมเดลของคุณ โหนดที่ชี้ไปยังคลิปที่โมเดลไม่มีจะล้มเหลวเงียบ ๆ และสัตว์จะแค่ยืนอยู่ในท่าอยู่เฉยของฐาน ให้โหนดของท่ามี m_ConditionPriority เป็น 10 เหมือนของฐาน และให้เลขสูงกว่ากับทุกอย่างที่ต้องเล่นทับมัน: 11 สำหรับท่าแปรผัน 12 สำหรับท่าเปลี่ยนทั้งสอง โหนดจะเล่นคลิปวนซ้ำถ้าคุณไม่บอกเป็นอย่างอื่น ดังนั้นทุกโหนดที่ตั้งใจให้เล่นครั้งเดียว ทั้งท่าเปลี่ยนทั้งสองและท่าแปรผันทุกอัน ต้องมี <m_Looped>false</m_Looped> ถ้าไม่มี คลิปจะเริ่มใหม่ทันทีที่จบ และสัตว์จะกระตุกกลับให้เห็นแล้วทำซ้ำอีกรอบ เพราะตัวแปรจะดับก็ต่อเมื่อถึงติกถัดไปของเซิร์ฟเวอร์ เก็บทั้งหมดไว้ใน idle/ เท่านั้น โหนดท่าที่อยู่ใน pathfind/ จะเล่นคลิปที่ไม่มี root motion และทำให้สัตว์ค้างอยู่กับที่
เสียง
ถ้าไม่มี voices ทุกสายพันธุ์ใช้เสียงของสุนัข แมวก็จะเห่า ลงทะเบียนเสียงของคุณเองก่อน
CD.registerVoices({
CDCatMeow = "bark", CDCatGrowl = "bark", CDCatHiss = "bark", CDCatPurr = "bark",
CDCatPet = "fx", CDCatMeowAmbient = "ambient",
})
แล้วชี้สายพันธุ์ไปที่เสียงเหล่านั้น
voices = { bark = "CDCatMeow", growl = "CDCatGrowl", idle = "CDCatPurr",
wildbark = "CDCatMeowAmbient", pet = "CDCatPet", whine = "CDCatHiss" },
ถ้าไม่มี CD.registerVoices เสียงยังดังอยู่ แต่มันเมินแถบเลื่อนหมวดเสียงของผู้เล่นและระดับเสียงเอฟเฟกต์ของเกม และไม่มีอะไรในล็อกชี้ให้เห็น คีย์ที่คุณไม่ได้ใส่ใน voices จะตกกลับไปใช้เสียงของสุนัข
whine คือเสียงที่สัตว์ร้องเมื่อบาดเจ็บหรือป่วย eat กับ drink คือเสียงกินและดื่ม ของสุนัขเป็นเสียงวนที่ตัวหลักจะหยุดเมื่อสัตว์กินเสร็จ ถ้าของคุณเป็นเสียงวนด้วย ให้ใส่ไว้ใน CD.SOUND_LOOPED แล้วตัวหลักจะหยุดให้ด้วยเมื่อผู้ฟังออกนอกระยะ ตัวหลักที่เก่ากว่า API 11 จะเมินสามคีย์นี้และเล่นเสียงของสุนัข
อาร์กิวเมนต์ตัวที่สามคือระยะที่ได้ยินของแต่ละเสียง เป็นจำนวนช่อง ควรตรงกับ distanceMax ที่คุณเขียนไว้ ในสคริปต์เสียงของคุณเอง
CD.registerVoices(map, nil, { CDCatMeow = 22, CDCatGrowl = 10 })
บนเซิร์ฟเวอร์ ฐานส่งเสียงไปให้เฉพาะผู้เล่นที่อยู่ในระยะนั้น ถ้าไม่ใส่ระยะ เสียงจะได้ระยะกลาง ๆ ตามหมวด เสียงฟ่อที่ควรไปได้สิบช่องจะออกไปถึงทุกคนในระยะสามสิบช่อง เลย distanceMax ไปแล้ว การลดทอนแบบผกผัน ของ FMOD จะหยุดลดแทนที่จะเงียบไป ไฟล์ .ogg ที่หลุดออกมาจึงดังอยู่ที่ distanceMin / distanceMax ของ ระดับเสียงตัวเองที่ระยะใดก็ตาม ให้ตั้ง distanceMin ไว้ต่ำกับเสียงดังของคุณด้วยเหตุผลเดียวกัน
อาหาร
ถ้าไม่มี diet ทุกสายพันธุ์กินเหมือนสุนัข อาหารที่เป็นพิษชุดเดียวกัน อาหารที่นับเป็นเนื้อชุดเดียวกัน และอาหาร ที่มันแทะจากรางชุดเดียวกัน ฟิลด์นี้เขียนทับสามรายการนั้นเฉพาะสายพันธุ์ของคุณ
diet = {
bad = { Fruits = true }, -- fruit now makes it sick
badParts = { onion = false }, -- onion no longer does
protein = { Cheese = true }, -- cheese now counts as meat
proteinParts = { tuna = true }, -- and so does anything with "tuna" in its type
trough = { Vegetables = false }, -- it will not graze vegetables
troughItems = { ["Base.CatFoodOpen"] = true },
},
สองรูปแบบนี้มีอยู่เพราะหมวดหมู่ของเกมเองไปได้ไม่สุด Cheese เป็น FoodType จริง คีย์เดียวจึงครอบคลุมชีส ทุกชิ้นในเกมและในม็อดอาหารใดก็ตามที่ใช้หมวดนั้นซ้ำ ปลาทูน่าไม่ใช่แบบนั้น กระป๋องที่เปิดแล้วคือ FoodType = Fish รวมกับปลาอื่นทั้งหมด ส่วนกระป๋องที่ยังไม่เปิดไม่ประกาศชนิดอาหารเลย badParts และ proteinParts คือทางที่คุณเอื้อมไปถึงของพวกนั้น
ทุกฟิลด์เป็นตารางของ <key> = true (เพิ่ม) หรือ <key> = false (ตัดสิ่งที่ฐานมีอยู่ออก) ค่าที่ไม่ใช่ true หรือ false จะถูกทิ้งพร้อมบรรทัดที่ระบุชื่อในล็อก
| ฟิลด์ | คีย์ของมันคืออะไร |
|---|---|
bad |
FoodType ของอาหารที่ทำให้สัตว์ป่วย ทำให้เสียความซื่อสัตย์ และได้รายการสีแดงในเมนูให้อาหาร |
badParts |
ชิ้นส่วนของชนิดไอเทม ตัวพิมพ์เล็ก จับคู่ที่ตำแหน่งใดก็ได้ในนั้น |
protein |
FoodType ที่ใช้หนี้เนื้อของสัตว์ ตัวเดียวกับที่ moodle Weak คอยจับตา |
proteinParts |
ชิ้นส่วนของชนิดไอเทม จับคู่แบบเดียวกับ badParts |
nonProtein |
FoodType ที่คุณรู้ว่าไม่ใช่เนื้อ มันแค่ปิดบรรทัดล็อกที่ฐานเขียนเมื่อเจอชนิดอาหารที่ไม่เคยเห็น |
trough |
FoodType และ AnimalFeedType ที่สัตว์กินเองจากรางอาหาร |
troughItems |
ชนิดไอเทมแบบเต็ม สำหรับไอเทมในรางที่ไม่มีชนิดอาหารสัตว์ของตัวเอง |
replace = true เริ่มจากรายการว่างแทนที่จะเริ่มจากรายการของสุนัข ใช้มันเมื่อสัตว์ของคุณแทบไม่มีอะไรร่วมกับ สุนัขเลย ส่วนแมวมักเขียนง่ายกว่าด้วยการเพิ่มและตัดออกไม่กี่รายการ
รายการทั้งสามติดตัวสัตว์ไป สุนัขกับแมวที่ยืนอยู่ที่รางเดียวกันจึงกินคนละอย่างจากมัน ชามของม็อดเองเป็นข้อยกเว้น มันเก็บแต้มอาหาร ไม่ใช่ไอเทมที่เติมลงไป การเติมชามจึงใช้รายการของฐานสำหรับทุกตัว และของมีพิษก็ใส่ลงชาม ไม่ได้อยู่แล้ว
เพศตอนเกิด
สัตว์ทุกตัวจะสุ่มเพศผู้หรือเมียตอนโผล่มา ครึ่งต่อครึ่ง maleChance คือสัดส่วนที่เกิดเป็นตัวผู้ ตั้งแต่ 0 ถึง 1 และ sterileMale กันตัวผู้ของสายพันธุ์นั้นออกจากการผสมพันธุ์
maleChance = 0.00033,
sterileMale = true,
คู่นี้คือแมวสามสี ลายผสมส้มกับดำอยู่บนโครโมโซม X แมวสามสีจึงเกือบจะเป็นตัวเมียเสมอ ส่วนตัวผู้ที่หลุดออกมาได้คือ XXY ราวหนึ่งในสามพัน และให้ลูกไม่ได้ ตัวผู้ของสายพันธุ์ที่ตั้ง sterileMale จะไม่ถูกเลือกเป็นคู่ และตัวเลือกผสมพันธุ์จะหายไป จากเมนูคลิกขวาของมัน ตัวเมียผสมพันธุ์ได้ตามปกติ
ตัวผู้ของสายพันธุ์แบบนี้จะติดป้าย "เป็นหมัน" ทุกที่ที่เกมแสดงเพศของมัน ทั้งในแผ่นข้อมูล เมนูคลิกขวา การสำรวจสัตว์จรจัด และคอกสัตว์ ผู้เล่นจะได้รู้ว่าทำไมมันถึงไม่ผสมพันธุ์
ทั้งสองช่องอ่านจากนิยามของสายพันธุ์ จึงไม่มีอะไรถูกเขียนลงบนตัวสัตว์ และเซฟเดิมไม่ต้องย้ายข้อมูล การสุ่มชุดเดียวกันนี้ ตัดสินเพศของลูกตอนคลอดด้วย สายพันธุ์ที่เป็นตัวเมียในโลกจึงยังเป็นตัวเมียในครอกที่เกิดมา
6. การปิดทั้งระบบ
ทักษะทั้งห้าคือระบบทั้งห้า
| ทักษะ | เป็นระบบอะไร |
|---|---|
scent |
ผู้เฝ้าระวัง: สังเกตซอมบี้และเตือนคุณ |
combat |
การต่อสู้ โหมดเฝ้าระวัง และการป้องกันตัว |
obedience |
ต้นไม้ท่าทาง |
hunt |
การล่าสัตว์ บวกโบนัสการหาของที่มันให้เจ้าของ |
herding |
การดูแลปศุสัตว์ในคอก |
สปีชีส์หนึ่งจึงประกาศสิ่งที่มันไม่มี
skills = { combat = false, herding = false },
canBreed = false,
huntMaxPrey = "tiny",
ไม่ระบุหรือ true แปลว่าสัตว์ตัวนั้นมีทักษะนั้น
การปิดทักษะยังหยุดการได้รับค่าประสบการณ์ของทักษะนั้น และเอาแถบกับคำสั่งของมันออกจากอินเทอร์เฟซด้วย
canBreed = false แยกออกมาจากตารางเพราะการผสมพันธุ์ไม่มีแถบและไม่มีค่าประสบการณ์ สัตว์ตัวนั้นจะไม่ตั้งท้อง ไม่เคยถูกเลือกเป็นคู่ และไม่ผสมกับพวกเดียวกันเองด้วย
สปีชีส์
แอดออนที่เพิ่มสัตว์ชนิดอื่นเข้ามา แทนที่จะเป็นสุนัขอีกตัว ต้องประกาศแบบนี้
CD.registerSpecies({ key = "cat",
nounKey = "IGUI_PD_SpeciesNoun_cat",
youngKey = "IGUI_PD_Young_cat" })
CD.registerBreed({ ..., species = "cat" })
ฟิลด์นี้ไม่มีในทุกสายพันธุ์ที่เผยแพร่มาจนถึงตอนนี้ และการไม่มีแปลว่า "dog"
การผสมพันธุ์ปิดอยู่ในสปีชีส์เดียวกัน: คู่หนึ่งจะตั้งท้องก็ต่อเมื่อทั้งสองฝ่ายเป็นสปีชีส์เดียวกัน ทั้งในคำสั่ง ในการทอยรายชั่วโมงแบบเงียบ ๆ และในเครื่องมือดีบัก และอินเทอร์เฟซจะเลิกเรียกสัตว์ของคุณว่าหมา: nounKey คือคำนามเปล่า ๆ ที่เติมลงในประโยคอย่าง "%1 เป็นของผู้รอดชีวิตคนอื่นแล้ว" ส่วน youngKey คือป้ายที่ตัวเล็กของสปีชีส์คุณใช้ในหน้าต่าง เมนูคลิกขวา และคอก ซึ่งหมาจะขึ้นว่า ลูกสุนัข
คำนามสองคำนั้นครอบคลุมแค่ประโยคที่สร้างรอบ ๆ %1 เท่านั้น ประโยคอื่นทุกประโยคที่มีคำว่า หมา เขียนอยู่ในตัวมันเอง ("ตรวจดู", "สุนัขของคุณกำลังหิว", "หมาเห่าเพื่อล่อพวกมันไป") ตั้งแต่ API 7 เป็นต้นไปจะใช้คีย์รายสปีชีส์: ใส่ IGUI_PD_ScanStray_cat ไว้ในไฟล์แปลของคุณ แล้วตัวหลักจะแสดงคีย์นั้น แทน IGUI_PD_ScanStray ทุกครั้งที่สัตว์บนหน้าจอเป็นแมว คีย์ที่คุณไม่ได้ใส่มาจะถอยไปใช้ข้อความของหมา คีย์ที่รับคำต่อท้ายได้มี ScanStray, ScanTitle, PauseGrowthTip, BadFood, AlertFullDesc, AlertQuietDesc, AlertLockedTip, HuntModeDesc, ทุกตัวที่เป็น Trick*Desc, TrickDistractDone, TrickNeedsBag, TrickGotoPick, TrickSniffNoItem, TrickFetchNoItem, AlertGroup, DogLost, ทุกตัวที่เป็น Refused_*, KennelStatusNoData และ Moodle_*_desc ของ moodle การดูแล (Sick, Weak, Hunger, Thirst, Rested, Grief) ประโยคที่ไม่มีสัตว์อยู่บนหน้าจอ (แท็บทะเบียน, "ผูกมิตรกับสัตว์ก่อน") เป็นกลางทางสปีชีส์อยู่แล้วในตัวหลัก แมวใส่มาครบทั้งสิบสี่ภาษา ให้ใช้ IG_UI.json ของมันเป็นแม่แบบ
group ของสัตว์ถูกอ่านโดยเมนูสปอว์นในโหมดดีบักและตัวดูคลิปเท่านั้น ผ่าน IGUI_Animal_Group_<group> ตั้ง t.group = "cat" หลังตัวช่วยพฤติกรรม แล้วใส่คีย์นั้นมาด้วย ไม่อย่างนั้นสปีชีส์ของคุณจะไปโผล่ตรงนั้น ในชื่อของหมา
การประกาศ species โดยไม่ลงทะเบียนมันไม่ถึงตาย สัตว์ของคุณยังปฏิเสธการผสมนอกสปีชีส์ตัวเองอยู่ดี เพราะด่านนี้เทียบสตริงดิบ มีแค่คำนามสองคำที่ถอยไปใช้ของหมา และล็อกจะบอกเรื่องนี้พร้อมระบุชื่อ
บนตัวหลักที่เก่ากว่า API 6 ฟิลด์นี้จะถูกเมินโดยไม่มีบรรทัดในล็อก และสัตว์ของคุณจะผสมพันธุ์อย่างหมา ถ้ามันต้องไม่ข้ามกับหมาเด็ดขาด ให้ตั้งด่านที่ API 6 หรือคง canBreed = false ไว้ระหว่างที่ตัวหลักยังเก่า ซึ่งเป็นสิ่งที่แมวทำ
huntMaxPrey จำกัดขนาดเหยื่อภายในการล่าที่ยังมีอยู่ มันไม่ได้แทน hunt = false มันรับค่า "tiny" (หนู กระรอก), "small" (กระต่าย แรคคูน) หรือ "large" (กวาง เป็นค่าเริ่มต้น ไม่จำกัด) สัตว์ของคุณจะไม่ไล่และไม่ชี้เหยื่อที่ใหญ่เกินขีดจำกัด ค่าที่อยู่นอกบันไดนี้จะถอยไปเป็น "large" และพิมพ์บรรทัดที่ระบุชื่อลงในล็อก
ตัวเลือกที่ถูกปิดจะหายไปจากเมนูวงกลม เมนูคลิกขวา และหน้าต่าง และเซิร์ฟเวอร์จะปฏิเสธมันโดยไม่มีข้อความ ไม่มีฟิลด์ไหนในนี้ที่เพิ่มคีย์การแปล ให้อธิบายข้อจำกัดไว้ในคำอธิบายสายพันธุ์ของคุณ
7. นิยามของสัตว์
เอนจินผูกเมชเข้ากับไทป์ของสัตว์ ไม่ใช่กับสายพันธุ์ สายพันธุ์ของคุณจึงต้องมีไทป์ของตัวเองสามอัน ทางที่สั้นที่สุดคือคัดลอกไฟล์ของแอดออนที่มีอยู่แล้วเปลี่ยนชื่อ
สามส่วนนี้ อยู่ในไฟล์ shared ไฟล์เดียวใต้ Definitions/animal/
AnimalDefinitions.stages["pug"] = {}
AnimalDefinitions.stages["pug"].stages = {}
AnimalDefinitions.stages["pug"].stages["pugpup"] = {}
AnimalDefinitions.stages["pug"].stages["pugpup"].ageToGrow = 3 * 30
AnimalDefinitions.stages["pug"].stages["pugpup"].nextStage = "pugfemale"
AnimalDefinitions.stages["pug"].stages["pugpup"].nextStageMale = "pugmale"
AnimalDefinitions.breeds["pug"].breeds["pug"].texture = "Pug"
AnimalDefinitions.breeds["pug"].breeds["pug"].textureMale = "Pug"
AnimalDefinitions.breeds["pug"].breeds["pug"].rottenTexture = "Raccoon_Rotting"
AnimalDefinitions.breeds["pug"].breeds["pug"].invIconMale = "CDDogPaw_64"
AnimalDefinitions.breeds["pug"].breeds["pug"].invIconMaleDead = "CDDogPawDead_64"
local pugfemale = {}
CD.applyDogModel(pugfemale, "Pug_Body")
CD.applyDogBehaviour(pugfemale)
pugfemale.female = true
pugfemale.babyType = "pugpup"
pugfemale.minSize = 1.5
pugfemale.maxSize = 2.0
pugfemale.minWeight = 5
pugfemale.maxWeight = 8
pugfemale.wildFleeTimeUntilDeadTimer = CD.STRAY_NO_BLEEDOUT
pugfemale.breeds = AnimalDefinitions.breeds["pug"].breeds
pugfemale.stages = AnimalDefinitions.stages["pug"].stages
pugfemale.genes = AnimalDefinitions.genome["dog"].genes
AnimalDefinitions.animals["pugfemale"] = pugfemale
ตัวช่วยที่ตัวหลักให้มา
| ตัวช่วย | เติมอะไรให้ |
|---|---|
CD.applyCompanionModel(t, "Body_Model") |
โมเดลลำตัว โครงกระดูก เท็กซ์เจอร์ตอนชำแหละ และชุดแอนิเมชัน |
CD.applyCompanionBehaviour(t) |
ธงพฤติกรรมของเอนจินทุกอันที่สัตว์คู่หูต้องมี |
CD.applyCompanionAvatar(t) |
กล้องถ่ายภาพเหมือนสำหรับหน้าต่างของสัตว์ |
CD.COMPANION_SOUNDS |
ตารางเสียงฝีเท้าและเสียงประกอบที่ใช้ร่วมกัน |
CD.defineGenome("species") |
จีโนมของสปีชีส์ใหม่ พร้อมรายการยีนมาตรฐาน (API 7) |
CD.STRAY_NO_BLEEDOUT |
ค่าที่กันไม่ให้สัตว์จรจัดที่ตกใจเลือดไหลจนตาย |
CD.defineCompanionParts(typePrefix, engineBreed, meat) |
ชิ้นส่วนจากการชำแหละของทั้งสามช่วงวัย meat ไม่บังคับ: { item, minNb, maxNb, pupMinNb, pupMaxNb } และถ้าไม่ใส่ สัตว์จะให้เนื้อหมาของตัวหลัก เอนจินคูณทั้งจำนวนและค่าความอิ่มของทุกชิ้นด้วยขนาดของซาก สปีชีส์ที่มีขนาดใหญ่ (แมวใช้ 2.5 ถึง 3.5 เป็นสเกลที่มองเห็น) จึงต้องมีไอเทมของตัวเองที่มีค่าความอิ่มพื้นฐานต่ำกว่าและจำนวนน้อย |
ชื่อที่เป็นกลางทางสปีชีส์มาพร้อม API 7 ส่วนชื่อเก่ากว่า คือ CD.applyDogModel, CD.applyDogBehaviour, CD.applyDogAvatar, CD.DOG_SOUNDS, CD.defineDogParts และ CD.DogMoodles เป็นฟังก์ชันและตาราง เดียวกันภายใต้ชื่อแรกของมัน แอดออนที่อยากโหลดบนตัวหลักที่เก่ากว่า 0.7.3 ให้ตั้งด่านที่ชื่อเก่าและเลือก ชื่อใหม่เมื่อมันมีอยู่: local applyModel = CD.applyCompanionModel or CD.applyDogModel
ชุดแอนิเมชันต้องเป็น "raccoon" ต่อไป ชุดแอนิเมชันที่แยกสาขาออกไปจะไม่โหลดเครื่องสถานะของมัน และสัตว์จะยืนแข็งอยู่กับที่
ใช้จีโนมซ้ำ สายพันธุ์หมาชี้ไปที่รายการของตัวหลัก: AnimalDefinitions.genome["dog"].genes สปีชีส์ใหม่เรียก CD.defineGenome("cat") หนึ่งครั้งแล้วให้ทุกช่วงวัยใช้ตารางที่มันคืนมา เอนจินอ่านแค่รายการ genes ของแต่ละช่วงวัย และคีย์จีโนมเป็นแค่ธรรมเนียม สปีชีส์ของคุณจึงได้รายการ ของตัวเองโดยไม่ต้องมีรายการยีนของตัวเอง
อย่าประกาศ mate ถ้ามีมัน เอนจินจะรันการผสมพันธุ์ของมันเองภายในโซนสัตว์ใด ๆ ซึ่งเมินบล็อกการผสมพันธุ์ ของม็อดและตัวเลือกแซนด์บ็อกซ์ของมัน และให้ลูกสุนัขที่ไม่มีความผูกพัน ตัวหลักล้างฟิลด์นี้ตอนบูต แต่อย่าไปพึ่งมัน
ชิ้นส่วนเป็นสิ่งบังคับ สามบรรทัดในไฟล์ของมันเอง
if CompanionDogs and CompanionDogs.defineDogParts then
CompanionDogs.defineDogParts("pug", "pug")
end
ถ้าไม่มี การชำแหละสัตว์ของคุณจะทำให้โค้ดของเกมหลักพัง เพราะมันอ้างนิยามชิ้นส่วนด้วยไทป์และสายพันธุ์ แล้วไปเจอ nil
การซูมภาพเหมือนใน CD.applyDogAvatar ปรับเทียบไว้สำหรับหมา และการซูมของอวตารคือกำลังขยาย สัตว์ยิ่งเล็ก ตัวเลขยิ่งมาก ให้หารค่าซูมด้วยอัตราส่วนขนาดเทียบกับหมา และคูณค่าออฟเซ็ตด้วยอัตราส่วนนั้น ไม่อย่างนั้นสัตว์ของคุณจะนั่งจิ๋วอยู่ก้นภาพเหมือนของตัวเอง
8. สคริปต์ของโมเดล
ไฟล์เดียวใต้ media/scripts/ บอกเกมว่าโมเดลของคุณมีอยู่
module Base
{
model Pug_Body
{
mesh = Skinned/Pug_Body,
shader = animalEffect,
static = false,
animationsMesh = PugAnim,
attachment head
{
offset = -0.0061 0.1671 0.0507,
rotate = -179.0 -5.0 95.0,
bone = Dummy01,
}
}
animationsMesh PugAnim
{
meshFile = Skinned/Pug_Body,
keepMeshAnimations = true,
}
}
keepMeshAnimations = true ทำให้คลิปที่อยู่ในไฟล์โมเดลของคุณยังใช้ได้ ถ้าไม่มีมัน โมเดลจะโหลดขึ้นมา แล้วไม่ขยับเลย
จุดยึด head คือที่ที่หมวกและของทำนองนั้นไปนั่งอยู่ ถ้าอยากให้กระเป๋าอานเข้ากับสัตว์ของคุณ ให้เพิ่ม saddlebags_l, saddlebags_r และ saddlebags_c แบบเดียวกันบนกระดูกสันหลัง หาตัวเลขพวกนั้นด้วยการมองสัตว์ในเกมแล้วขยับทีละนิด ค่าที่วัดจากโมเดลจะวางกระเป๋าไว้ตรงจุดศูนย์กลาง เชิงเรขาคณิตของเมช ซึ่งไม่ใช่ตำแหน่งที่ดูเข้าที่บนตัวสัตว์
9. สัตว์ตัวนี้โผล่ที่ไหน
สัตว์จรจัดถูกทอยเป็นรายอาคาร รายชังก์ ในครั้งแรกที่ชังก์นั้นโหลด คุณอธิบายการทอยของคุณเป็นรายการขั้นตอน จะอยู่ในนิยามสายพันธุ์ในชื่อ spawns หรือใช้ CD.registerStraySpawns(list) ก็ได้
spawns = {
{ id = "pughouse", class = "house", suffix = "|pg", breed = "pug", indoor = 85,
chance = function() return CD.strayChancePerHouse() / CD.PUG_HOUSE_RARITY end },
{ id = "pugpetvet", class = "petvet", suffix = "|pv", breed = "pug",
chance = function() return CD.PUG_PETVET_CHANCE * CD.dogSpawnMultiplier() end },
},
| คีย์ | คืออะไร |
|---|---|
id |
ชื่อของขั้นตอน ไว้ใช้ในล็อกของคุณเอง |
class |
คลาสของอาคารที่ใช้ทอย |
chance |
ฟังก์ชันที่คืนค่าเปอร์เซ็นต์ จึงอ่านตัวคูณของแซนด์บ็อกซ์ได้ตอนทอย |
suffix |
คีย์ของที่เก็บถาวร ต้องไม่ซ้ำกับม็อดใดเลย และห้ามเปลี่ยน |
breed |
คีย์สายพันธุ์ที่จะให้เกิด |
gate |
ฟังก์ชันที่ไม่บังคับ คืนค่าจริงเท็จ ตรวจก่อนทอย Husky ใช้ CD.isWinter |
indoor |
เปอร์เซ็นต์โอกาสที่จะเกิดในตัวอาคารแทนที่จะเป็นถนน ค่าเริ่มต้นคือ 35 |
คูณโอกาสของคุณด้วย CD.dogSpawnMultiplier() หรือหาร CD.strayChancePerHouse() ด้วยค่าความหายาก ของคุณเอง ทั้งสองวิธีทำให้ค่าแซนด์บ็อกซ์ของผู้เล่นยังทำงานอยู่
indoor เป็นแค่ความต้องการ อาคารที่ไม่มีช่องว่างข้างในในชังก์นั้นจะถอยไปใช้ช่องนอกอาคารแทน
คลาสของอาคาร
ตัวหลักลงทะเบียนไว้สี่คลาส
| คลาส | ตรงกับอะไร |
|---|---|
house |
อาคารที่พักอาศัยที่ไม่ใช่ร้านค้า |
police |
สถานีตำรวจและอาคารทำนองเดียวกัน |
petvet |
ร้านขายสัตว์เลี้ยงและคลินิกสัตวแพทย์ |
farm |
อาคารในฟาร์ม และอนุญาตให้อยู่นอกเมืองได้ |
ถ้าไม่มีคลาสไหนเข้ากับคุณเลย ให้ลงทะเบียนของตัวเอง
CD.registerBuildingClass("mineshaft", function(def) return def:isX() end,
{ skipUrbanGate = true })
ฟังก์ชันตรวจคู่จะได้รับนิยามของอาคาร และทำงานอยู่ในการเรียกแบบป้องกัน ข้อผิดพลาดในนั้นจึงไม่หยุด การโหลดชังก์ skipUrbanGate ทำให้คลาสทอยได้ในชังก์ที่ไม่ใช่เขตเมือง ซึ่งฟาร์มหรือกระท่อมในป่าจำเป็นต้องใช้ อย่าตั้ง exclusive คลาสของตัวหลักกันเองอยู่แล้ว ส่วนคลาสของแอดออนจะเข้าคู่ทับลงไปอีกชั้นหนึ่ง
คำต่อท้ายที่มีคนใช้แล้ว
คำต่อท้ายเป็นส่วนหนึ่งของคีย์ที่ใช้บันทึกว่า "อาคารนี้ทอยไปแล้ว" ม็อดสองตัวที่ใช้คำต่อท้ายเดียวกัน จะทำให้การทอยของกันและกันเสียหาย
คำต่อท้ายทุกอันขึ้นต้นด้วยขีดตั้ง อันที่ใช้ไปแล้วมีดังนี้
- ตัวหลัก: คำต่อท้ายว่าง และ
g,h,hv,bc,gh,hh,bh - ร็อตไวเลอร์:
rw,r - โดเบอร์แมน:
db,dm,dh - ลาบราดอร์:
lb,lk - ปั๊ก:
pg,pv - มาลินอยส์:
ml,mm,mh - แมว: คำต่อท้ายทุกอันที่ขึ้นต้นด้วย
ct,cvหรือcs(หนึ่งชุดต่อหนึ่งสีขน)
10. moodle ของสายพันธุ์
moodle เป็นไฟล์ฝั่งไคลเอนต์ คุณเพิ่มตารางเข้าไปใน CD.DogMoodles แล้วตัวหลักจะวาดให้ ติดตามให้ และเก็บกวาดให้เอง
CD.DogMoodles[#CD.DogMoodles + 1] = {
id = "shadow",
breed = "pug",
nameKey = "IGUI_PD_Moodle_Shadow",
descKey = "IGUI_PD_Moodle_Shadow_desc",
icon = "CD_Moodle_Shadow",
fg = "CD_MoodShadowFG",
tintR = 0.92, tintG = 0.52, tintB = 0.68,
condition = function(player, dog)
if not dog or dog:isDead() then return 0 end
if CD.getBreed(dog) ~= "pug" then return 0 end
if CD.isDisloyal(dog) then return 0 end
return 1
end,
apply = function(player, dog, elapsedMin)
CD.relieveMood(player, CD.moodleReliefPerMin() * elapsedMin)
end,
}
condition คืนค่าระดับ หรือ 0 แปลว่า "ไม่แสดง" ส่วน apply ได้รับจำนวนนาทีในเกมนับจากการเรียก ครั้งก่อน ให้คูณเอฟเฟกต์ของคุณด้วย elapsedMin
ใส่ไอคอนมาให้ครบหกขนาด ตั้งแต่ 32 ถึง 128 พิกเซล อินเทอร์เฟซจะเลือกขนาดตามการปรับสเกลของผู้เล่น และขนาดที่ขาดไปจะขึ้นเป็นสี่เหลี่ยมว่าง ไอคอนจะไปอยู่ในแถบของม็อดเอง ไม่ปนกับ moodle ของเกมหลัก
11. ฮุก
รายการฟังก์ชันสองชุดที่ตัวหลักเรียกบนเซิร์ฟเวอร์ ให้เพิ่มเข้าไปจากไฟล์ shared ตัวจัดการแต่ละตัว ทำงานอยู่ในการเรียกแบบป้องกันของตัวเอง ข้อผิดพลาดในแอดออนหนึ่งจึงไม่หยุดตัวหลัก
CD.onHuntDelivered มีตั้งแต่ API 2 ถูกเรียกทันทีหลังจากสัตว์วางเหยื่อลงที่เท้าเจ้าของ
CD.onHuntDelivered[#CD.onHuntDelivered + 1] = function(animal, owner)
-- server side, so this is the right place to write mod data
end
CD.onUpkeepStress มีตั้งแต่ API 3 ถูกเรียกทุกรอบการดูแล หลังจากที่ตัวหลักบวกความเครียดจากความ ต้องการที่ไม่ได้รับการตอบสนองแล้ว และก่อนที่จะเขียนลงไป ให้คืนค่าตัวเลข ซึ่งจะถูกบวกเข้ากับผลรวม
CD.onUpkeepStress[#CD.onUpkeepStress + 1] = function(animal, needsStress)
return CD.pugHeatRatio(animal) * CD.PUG_HEAT_STRESS_MAX
end
การดูแลจะคำนวณใหม่และเขียนทับค่าทุกรอบ อะไรที่เขียนจากข้างนอกจึงหายไปในติกถัดไป ให้ใช้ฮุกกับ เงื่อนไขที่มาจากสภาพแวดล้อม เช่น ความร้อน ความหนาว หรือฝน
ในโหมดหลายคน ไคลเอนต์ไม่เขียน mod data เด็ดขาด การเขียนจากฝั่งไคลเอนต์จะทับสำเนาของเซิร์ฟเวอร์ ในการซิงก์ครั้งถัดไป และอาการจะโผล่ขึ้นมาอีกหลายนาทีให้หลังในที่ที่ไม่เกี่ยวกันเลย ให้ทำงานนี้ในไฟล์ ฝั่งเซิร์ฟเวอร์ หรือในฮุกเหล่านี้
ตัวเลขในแผง SERVER TUNING เป็นค่าคงที่ CD.* ธรรมดา และส่วนเสริมกำหนดค่าหนึ่งในนั้นจากไฟล์ shared หรือไฟล์เซิร์ฟเวอร์ตอนโหลดได้ ตั้งแต่ API 9 แผงจะถือค่าที่มีผลอยู่ตอนเซิร์ฟเวอร์โหลดเสร็จเป็นค่าเริ่มต้นของปุ่มปรับนั้น: มันจะคงอยู่จนกว่าแอดมินจะพิมพ์ทับ ปุ่มรีเซ็ตจะกลับมาที่ค่านี้ และแผงจะแสดงมันเป็นค่าเริ่มต้น บนฐานรุ่นเก่า แผงจะเขียนค่าจากโรงงานทับกลับไปทุกครั้งที่บูต ให้กำหนดค่าตอนโหลด ไม่ใช่จากเหตุการณ์ที่เกิดทีหลัง ไม่อย่างนั้นการเปลี่ยนปุ่มปรับตัวไหนก็ตามครั้งถัดไปจะดึงค่าจากโรงงานกลับมา
12. คีย์การแปล
ใส่ IG_UI.json หนึ่งไฟล์ต่อโฟลเดอร์ภาษา ใน media/lua/shared/Translate/<LANG>/ ตัวหลักใส่มา สิบสี่ภาษา: EN, PTBR, CH, CN, DE, ES, FR, IT, JP, KO, RU, TH, UA, VI
คีย์ที่สายพันธุ์หนึ่งต้องมี
| คีย์ | แสดงที่ไหน |
|---|---|
IGUI_PD_Breed_<key> |
ชื่อสายพันธุ์ ทุกที่ในอินเทอร์เฟซของม็อด |
IGUI_PD_BreedDesc_<key> |
คำอธิบายบนการ์ดของสัตว์ |
IGUI_Breed_<engineBreed> |
ชื่อสายพันธุ์ในหน้าจอของตัวเกมเอง |
IGUI_AnimalType_<type> |
หนึ่งอันต่อไทป์ทั้งสามของคุณ |
| คีย์สปีชีส์ของคุณ | nounKey และ youngKey ที่คุณส่งให้ CD.registerSpecies |
| คีย์ moodle ของคุณ | ทั้งชื่อและคำอธิบาย |
{
"IGUI_Breed_pug": "Pug",
"IGUI_AnimalType_pugmale": "Pug (male)",
"IGUI_AnimalType_pugfemale": "Pug (female)",
"IGUI_AnimalType_pugpup": "Pug (puppy)",
"IGUI_PD_Breed_pug": "Pug",
"IGUI_PD_BreedDesc_pug": "The house dog: the first companion whose worth is not fighting."
}
เครื่องหมายเปอร์เซ็นต์ตรง ๆ ในสตริงที่แปลแล้วจะทำให้หน้าจอที่แสดงมันพัง เพราะตัวจัดรูปแบบอ่านมันเป็น ตัวแทนค่า ไฟล์ภาษาที่มี byte order mark จะคอมไพล์ไม่ผ่าน และข้อผิดพลาดจะไปชี้ไฟล์อื่นที่ไม่ใช่ไฟล์ที่เสีย
13. สิ่งที่เซฟจดจำไว้
ตัวระบุสามอย่างของคุณถูกเขียนลงไฟล์เซฟและถูกอ่านกลับมาตลอดไป
keyตัวระบุสายพันธุ์ที่เก็บอยู่บนสัตว์ทุกตัวของคุณtypePrefixซึ่งประกอบขึ้นเป็นไทป์ของสัตว์ที่เอนจินเก็บไว้suffixคีย์ของที่เก็บ "ทอยไปแล้ว" หนึ่งอันต่อขั้นตอนการเกิดหนึ่งขั้น
ทั้งสามอย่างเปลี่ยนชื่อไม่ได้หลังปล่อยออกไปแล้ว การเปลี่ยนชื่อ key จะทำให้สัตว์ที่ยังมีชีวิตของสายพันธุ์นั้น กลายเป็นกำพร้าทั้งหมด การเปลี่ยนชื่อ suffix จะทำให้ทุกอาคารในทุกเซฟที่มีอยู่ถูกทอยใหม่ และโลกที่เล่นมา หลายเดือนจะเต็มไปด้วยสัตว์ของคุณ
คำต่อท้ายใหม่ยังเป็นวิธีที่สายพันธุ์ใหม่ไปถึงโลกที่เล่นอยู่แล้วด้วย CD: Cats ให้คำต่อท้ายใหม่กับสีขนใหม่ ทั้งสี่สี พวกมันจึงเริ่มโผล่ในเซฟที่มีอยู่ ส่วนแมวดำตัวเดิมยังใช้คำต่อท้ายเก่าและไม่ถูกทอยซ้ำ
การถอนแอดออนออกจากเซฟที่มีสัตว์สายพันธุ์นั้นยังมีชีวิตอยู่จะทำให้เสียมันไป เอนจินจะทิ้งสัตว์ที่มันไม่รู้จัก ไทป์อีกต่อไป ตัวหลักไม่พัง และความผูกพันกับคอกจะเสื่อมลงอย่างเรียบร้อย เขียนบอกเรื่องนี้ไว้ในหน้า Workshop ของคุณ
ถ้าแอดออนของคุณหายไป ตัวหลักจะถอยไปใช้สายพันธุ์เริ่มต้นสำหรับทุกอย่างที่มันถูกถาม เซฟที่เปิดโดยไม่มี ม็อดของคุณจึงยังอ่านได้
14. ก่อนเผยแพร่
- ตัวป้องกันอยู่ในไฟล์ Lua ทุกไฟล์ และระบุ API ที่คุณใช้จริง
- เวอร์ชันขั้นต่ำของตัวหลักเขียนไว้ในคำอธิบายเป็นตัวหนังสือ
versionMinบอกแทนไม่ได้ - คุณอ่านล็อกตอนโหลดครั้งแรกแล้ว ไม่อย่างนั้น
CD.registerBreedจะปฏิเสธเงียบ ๆ และการปฏิเสธ ทุกครั้งจะพิมพ์บรรทัดที่ระบุชื่อออกมา - เรียก
CD.defineDogPartsแล้ว ลองชำแหละสัตว์ของคุณสักตัวและดูว่ามันไม่พัง key,typePrefixและคำต่อท้ายการเกิดของคุณไม่ซ้ำใคร และคุณจะไม่ต้องเปลี่ยนมัน- สายพันธุ์ตัวเล็กตั้ง
puppySizeและคุณได้เห็นลูกสุนัขเป็นหลักฐานแล้ว - ถ้าเป็นสปีชีส์อื่น ต้องเรียก
CD.registerVoicesและเติมvoicesไว้ โดยมีwhineอยู่ในนั้นด้วย ไม่อย่างนั้นมันจะเห่าและร้องหงิงๆ เหมือนหมา - ไอคอน moodle มีครบทั้งหกขนาด
- ทุกโฟลเดอร์ภาษาที่คุณใส่มามีคีย์ครบทุกอัน คีย์ที่ขาดไปจะขึ้นเป็นคีย์ดิบบนหน้าจอ
- คุณทดสอบในโหมดหลายคนแล้ว ไม่ใช่แค่คนเดียว ตำแหน่ง ความเป็นเจ้าของ และ mod data ทำงานต่างกัน ในโหมดนั้น
- หน้า Workshop ของคุณเตือนเรื่องการถอนแอดออนออกจากเซฟที่มีสัตว์ยังมีชีวิตอยู่
15. ข้อผิดพลาดที่พบบ่อย
| อาการ | มันคืออะไร |
|---|---|
| "สัตว์ของผมไม่โผล่มาสักที" | เกือบทุกครั้งคือด่านตรวจ: ส่วนเสริมต้องใช้ API ที่ฐานที่ติดตั้งอยู่ไม่มี มันจึงออกจากไฟล์ทันทีและไม่ลงทะเบียนอะไรเลย |
| "มันโผล่มา แต่ค้าง" | ชุดแอนิเมชันไม่ใช่ "raccoon" หรือโมเดลขาดคลิป |
| "มันเรนเดอร์เป็นรอยดำและล็อกท่วม" | โมเดลมีกระดูกเกิน 60 ชิ้น |
| "ชำแหละมันแล้วเกมพัง" | ยังไม่ได้เรียก CD.defineDogParts |
| "ลูกสัตว์เกิดมาตัวเท่าตัวโต" | สายพันธุ์ตัวเล็กไม่ได้ตั้ง puppySize ค่านี้เป็นค่าสัมบูรณ์และถูกใส่ซ้ำในทุกรอบกวาด ดังนั้นช่วงขนาดของชนิดจึงไม่ครอบคลุมมัน |
| "สองสายพันธุ์ของผมกลายเป็นกันไปกันมา" | ทั้งสองใช้ engineBreed ร่วมกัน คำนำหน้าเลือกเมชและใช้ร่วมกันในตระกูลเดียวได้ แต่ engineBreed เลือกเท็กซ์เจอร์และแยกสายพันธุ์ในตระกูลนั้นออกจากกัน ดังนั้นมันต้องไม่ซ้ำกันในแต่ละสายพันธุ์ |
| "เสียงเล่นออกมาแต่ไม่สนใจแถบปรับระดับเสียง" | ยังไม่ได้เรียก CD.registerVoices ให้เสียงนั้น |
| "เล่นคนเดียวได้ แต่บนเซิร์ฟเวอร์ทำตัวแปลก ๆ" | มีอะไรเขียน ModData อยู่ที่ฝั่งไคลเอนต์ ย้ายไปที่เซิร์ฟเวอร์ |
| "มันสู้กับซอมบี้ทั้งที่ผมปิดการต่อสู้ไปแล้ว" | ฐานที่มันรันอยู่เก่ากว่า API 5 ฐานนั้นไม่รู้จักฟิลด์นี้และมองข้ามมันไป ด่านตรวจต้องกันไม่ให้โหลดบนฐานนี้ แทนที่จะโหลดต่อโดยไม่มีฟิลด์ |
มีอะไรในคู่มือนี้ผิดหรือขาดไปไหม บอกได้ที่ Discord