Skip to content

Commit 6d2dc8b

Browse files
committed
Dire ce que le tag apporte, place assise et interactions
Une chaise importee sur laquelle personne ne s'assoit ne manque pas d'une place assise : elle est rangee sous le mauvais tag. Sur les 2434 prefabs du jeu, 58 seulement nomment un NestedPrefabToSpawn, et aucun canape, tabouret ou banc n'en nomme. Ce qui rend un objet utilisable, c'est son tag de catalogue, par deux champs distincts de l'entree de tag dans BuildModeCatalogTags.setting : NestedPrefabToSpawn le gabarit de slot, sur 13 tags. Il contient le Seat, le ButtLocator et les locators de pieds, donc rien de l'animation n'est a ecrire. InteractionGroup ce qu'un Para peut faire avec, sur 47 tags. Les tags heritent, et c'est pour ca qu'Armchairs assoit un Para via Seating sans rien declarer lui-meme. Le selecteur dit desormais ce que le tag choisi apporte, juste sous le choix, et la checklist le repete. C'est une information et jamais une faute : la plupart des objets sont des decorations, et c'est voulu. Ce que ca ne couvre pas, et il faut le dire : la nourriture n'est pas un objet qu'on pose. FoodBreadRound porte Tag: s0, aucun tag, et le tag Food ne porte rien. Un mesh de nourriture exporte ne devient donc pas mangeable. Les lits sont l'autre trou : ils accrochent leurs places a un enfant porteur d'un ItemNestedPrefabSpawner plutot qu'au tag. Tests : 313 headless, 264 UI, traductions completes.
1 parent b8fa19a commit 6d2dc8b

7 files changed

Lines changed: 159 additions & 33 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Every entry below was driven by something measured in the game's own data
99
rather than assumed. Paralives is in early access, so the game build a finding
1010
was measured on is recorded with it.
1111

12-
## [0.23.0]
12+
## [0.24.0]
1313

1414
### Added
1515

@@ -38,9 +38,20 @@ was measured on is recorded with it.
3838
holds a Seat, a ButtLocator, a FeetFront and a FeetEnter, so nothing about
3939
the animation has to be authored.
4040

41-
The picker now says which template the chosen tag brings, right under the
42-
choice, and the checklist repeats it. It is information rather than a fault,
43-
since most items are decoration and are meant to be.
41+
Interactions are the tag's other field, `InteractionGroup`, on 47 tags: what
42+
a Para may do with a computer, a fridge, a range, a sink. Tags inherit, which
43+
is why `Armchairs` seats a Para through `Seating` without declaring anything
44+
itself.
45+
46+
The picker now says what the chosen tag brings, right under the choice, and
47+
the checklist repeats it. It is information rather than a fault, since most
48+
items are decoration and are meant to be.
49+
50+
What this does not cover: food is not a placeable item. `FoodBreadRound`
51+
carries `Tag: s0`, no tag at all, and the `Food` tag carries nothing, so a
52+
food mesh cannot be made edible by exporting it. Beds are the other gap: they
53+
hang their slots off a child object carrying an `ItemNestedPrefabSpawner`
54+
rather than off the tag.
4455

4556
## [0.22.0]
4657

‎paraforge/blender_manifest.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
schema_version = "1.0.0"
22

33
id = "paraforge"
4-
version = "0.23.0"
4+
version = "0.24.0"
55
name = "ParaForge"
66
tagline = "Convert and export Paralives Build Mode assets in one click"
77
maintainer = "infinition"

‎paraforge/catalog.py‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,3 +1821,85 @@ def tags_with_slots():
18211821
entry = BY_GUID.get(guid)
18221822
out.append((guid, entry[0] if entry else guid, template))
18231823
return sorted(out, key=lambda row: row[1])
1824+
1825+
# What a Para can do with an item is decided by its catalogue tag too, through
1826+
# a second field: InteractionGroup. 47 tags carry one, against 13 that carry a
1827+
# slot template, and the two are separate. Chairs carries both. Armchairs
1828+
# carries only the template and still seats a Para, because a tag inherits from
1829+
# its parents and Seating carries the interactions.
1830+
#
1831+
# Read out of Main.mod/Settings/BuildModeCatalogTags.setting.
1832+
1833+
INTERACTION_TAGS = {
1834+
"604085153922562519": "Baths",
1835+
"4628778472043362227": "Bedding",
1836+
"6444879227766942280": "Bookshelves",
1837+
"3400317259593598351": "CeilingFans",
1838+
"9105849566942677340": "Chairs",
1839+
"1616462328011360211": "Closets",
1840+
"7985540924855390150": "Computers",
1841+
"7447449227539394204": "Couches",
1842+
"8461709061774362586": "CountersAndCabinets",
1843+
"4647535654631335830": "Doors",
1844+
"5234230757320379395": "Dressers",
1845+
"4924269558178068359": "Fireplaces",
1846+
"460710503665464322": "FloorLamps",
1847+
"3591542995555286041": "Flowers",
1848+
"642202484693579278": "Frames",
1849+
"3108863021855919330": "Fridges",
1850+
"2779062035506052039": "Lighting",
1851+
"3090969998361602773": "Mailboxes",
1852+
"5676720021332220820": "Microwaves",
1853+
"3265636272264671824": "Mirrors",
1854+
"4076339812397061500": "Ranges",
1855+
"8535178522425522383": "Rugs",
1856+
"1577919339783889004": "Seating",
1857+
"2067641458504236188": "Showers",
1858+
"108320156183816049": "Sinks",
1859+
"6014339009269246888": "TVs",
1860+
"8901024204529792639": "TableLamps",
1861+
"3379229577763952217": "Toilets",
1862+
"8001521036836752277": "Trash",
1863+
"8372779771154572480": "Trash",
1864+
"3701994551219430330": "Trees",
1865+
"8634782218500074114": "_BedAdultModel",
1866+
"4575609469802988211": "_BedCrib",
1867+
"5855831541297902823": "_BuildableSandCastle",
1868+
"4369724328259993374": "_CityJournalDispenser",
1869+
"8243536152945723335": "_CityTrafficCone",
1870+
"758181910550224109": "_DrawablePaper",
1871+
"5564997046115680029": "_EducativeBook",
1872+
"4530928373772042014": "_EducativeToy",
1873+
"5615717779103809048": "_FlowerBushsAndPlanters",
1874+
"2285893339648069873": "_Guitar",
1875+
"9009564337597788863": "_HighChair",
1876+
"2616680388127829501": "_PlayableHopscotch",
1877+
"6333900641183854484": "_PlayablePlush",
1878+
"4741678931641170149": "_SittableBench",
1879+
"523991108259902175": "_ToddlersToy",
1880+
"6713782805470202312": "_Well",
1881+
}
1882+
1883+
1884+
def _up(guid, table):
1885+
"""Walk a tag and its ancestors, returning the first hit in table."""
1886+
seen = set()
1887+
current = guid
1888+
while current and current not in seen:
1889+
seen.add(current)
1890+
if current in table:
1891+
return table[current]
1892+
entry = BY_GUID.get(current)
1893+
if entry is None:
1894+
return ""
1895+
current = entry[1]
1896+
return ""
1897+
1898+
1899+
def interaction_source(guid):
1900+
"""The tag that brings the interactions, which may be an ancestor."""
1901+
return _up(guid, INTERACTION_TAGS)
1902+
1903+
1904+
def has_interactions(guid):
1905+
return bool(interaction_source(guid))

‎paraforge/i18n.py‎

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -430,15 +430,18 @@ def pick(french, english):
430430
"Used by a Para": "Utilisé par un Para",
431431
"A tag typed by hand, so this cannot be checked":
432432
"Un tag saisi à la main, donc invérifiable ici",
433-
"The tag attaches {0}, so a Para can use it":
434-
"Le tag attache {0}, un Para peut donc s'en servir",
435-
"The tag attaches {0}, which is a sound rather than a place to sit":
436-
"Le tag attache {0}, qui est un son et non une place assise",
437-
"Decoration: this tag attaches nothing, so a Para will walk past it. "
438-
"Seating lives under Chairs, Armchairs, OfficeChairs, Couches or Benches":
439-
"Décoration : ce tag n'attache rien, un Para passera donc à côté. "
440-
"Les assises sont sous Chairs, Armchairs, OfficeChairs, Couches ou "
441-
"Benches",
433+
"This tag brings ": "Ce tag apporte ",
434+
"a place to sit, from {0}": "une place assise, depuis {0}",
435+
"{0}, which is a sound rather than a place":
436+
"{0}, qui est un son et non une place",
437+
"interactions, from the {0} tag": "des interactions, depuis le tag {0}",
438+
"Decoration: this tag brings neither a place to sit nor an interaction, "
439+
"so a Para will walk past it. Seating lives under Chairs, Armchairs, "
440+
"OfficeChairs, Couches or Benches":
441+
"Décoration : ce tag n'apporte ni place assise ni interaction, un Para "
442+
"passera donc à côté. Les assises sont sous Chairs, Armchairs, "
443+
"OfficeChairs, Couches ou Benches",
444+
"Interactions from ": "Interactions depuis ",
442445
"A Para can use it: ": "Un Para peut s'en servir : ",
443446
"Attaches ": "Attache ",
444447
"Decoration, no Para uses it": "Décoration, aucun Para ne s'en sert",

‎paraforge/ui.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,14 @@ def _draw_target(self, context, layout, settings):
112112
# template the game attaches, so a chair filed under the wrong one
113113
# is furniture nobody sits on.
114114
template = catalog.slot_template(settings.catalog_tag)
115+
source = catalog.interaction_source(settings.catalog_tag)
115116
hint = column.row()
116117
hint.scale_y = 0.7
117118
if catalog.seats_a_para(settings.catalog_tag):
118119
hint.label(text=_("A Para can use it: ") + template,
119120
icon="OUTLINER_OB_ARMATURE")
121+
elif source:
122+
hint.label(text=_("Interactions from ") + source, icon="PLAY")
120123
elif template:
121124
hint.label(text=_("Attaches ") + template, icon="SOUND")
122125
else:

‎paraforge/validate.py‎

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,23 @@ def _check_facing(settings, report):
231231
def _check_usable(settings, report):
232232
"""Whether a Para will ever do anything with the item.
233233
234-
A chair carries no seat of its own. Nothing in its prefab says where to
235-
sit, and the 29 shipped chairs that do carry a NestedPrefabToSpawn are the
236-
exception. What makes an item usable is its catalogue tag: the tag entry in
237-
BuildModeCatalogTags.setting carries the template, and the game attaches it
238-
to everything filed under that tag.
239-
240-
So an imported chair filed under the wrong tag is furniture nobody sits on,
241-
and the Para walks to another chair instead. That is not something the
242-
export can fix, only the tag can, which is why this reads as information
243-
next to the choice rather than as a fault.
234+
A chair carries no seat of its own. Of the game's 2434 prefabs only 58 name
235+
a NestedPrefabToSpawn, and no couch, stool or bench names one. What makes
236+
an item usable is its catalogue tag, through two separate fields on the tag
237+
entry in BuildModeCatalogTags.setting:
238+
239+
NestedPrefabToSpawn the slot template, on 13 tags. It holds the Seat,
240+
the ButtLocator and the foot locators, so nothing
241+
about the animation has to be authored.
242+
InteractionGroup what a Para may do with it, on 47 tags.
243+
244+
Tags inherit, so Armchairs seats a Para through Seating without declaring
245+
anything itself.
246+
247+
An imported chair filed under the wrong tag is furniture nobody sits on,
248+
and the Para walks to another chair instead. The export cannot fix that,
249+
only the tag can, which is why this reads as information next to the choice
250+
rather than as a fault: most items are decoration and are meant to be.
244251
"""
245252
tag = settings.catalog_tag
246253
if tag == spec.CUSTOM_TAG:
@@ -249,20 +256,26 @@ def _check_usable(settings, report):
249256
return
250257

251258
template = catalog.slot_template(tag)
259+
source = catalog.interaction_source(tag)
260+
parts = []
261+
252262
if catalog.seats_a_para(tag):
263+
parts.append(_("a place to sit, from {0}", template))
264+
elif template:
265+
parts.append(_("{0}, which is a sound rather than a place", template))
266+
267+
if source:
268+
parts.append(_("interactions, from the {0} tag", source))
269+
270+
if parts:
253271
report.add("usable", _("Used by a Para"), OK,
254-
_("The tag attaches {0}, so a Para can use it", template))
255-
return
256-
if template:
257-
report.add("usable", _("Used by a Para"), OK,
258-
_("The tag attaches {0}, which is a sound rather than a "
259-
"place to sit", template))
272+
_("This tag brings ") + ", ".join(parts))
260273
return
261274

262275
report.add("usable", _("Used by a Para"), OK,
263-
_("Decoration: this tag attaches nothing, so a Para will walk "
264-
"past it. Seating lives under Chairs, Armchairs, "
265-
"OfficeChairs, Couches or Benches"))
276+
_("Decoration: this tag brings neither a place to sit nor an "
277+
"interaction, so a Para will walk past it. Seating lives "
278+
"under Chairs, Armchairs, OfficeChairs, Couches or Benches"))
266279

267280

268281
def _check_asset_name(objects, settings, report):

‎tests/test_headless.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,20 @@ def test_usable_by_a_para():
14261426
"13 tags attach something, out of the game's 298",
14271427
str(len(cat.tags_with_slots())))
14281428

1429+
# Interactions are the tag's other field, and tags inherit, which is why
1430+
# an armchair seats a Para without declaring anything itself.
1431+
check(cat.interaction_source(cat.BY_NAME["Chairs"]) == "Chairs",
1432+
"a tag can carry its own interactions")
1433+
check(cat.interaction_source(cat.BY_NAME["Armchairs"]) == "Seating",
1434+
"or inherit them from a parent tag",
1435+
cat.interaction_source(cat.BY_NAME["Armchairs"]))
1436+
check(cat.has_interactions(cat.BY_NAME["Computers"]),
1437+
"a computer has interactions and no seat")
1438+
check(not cat.has_interactions(cat.BY_NAME["Build"]),
1439+
"and the root Build tag has neither")
1440+
check(not cat.has_interactions(cat.BY_NAME["Food"]),
1441+
"nor does Food, which is not a placeable item at all")
1442+
14291443
fresh_scene()
14301444
make_cube()
14311445
settings = props.settings(bpy.context)

0 commit comments

Comments
 (0)