P23-03: 生活の観察
This commit is contained in:
@@ -1561,6 +1561,50 @@ func _life_track_region(key: String, cell: Vector3i, model: Dictionary) -> Dicti
|
||||
return {&"bounds": rect, &"transit": transit}
|
||||
|
||||
|
||||
## Keep non-passengers on a real corridor landing when a cabin crosses their pose.
|
||||
func _life_landing_region(region: Dictionary, cell: Vector3i, model: Dictionary) -> Dictionary:
|
||||
var blocked := false
|
||||
for cabin: Dictionary in model[&"cabins"]:
|
||||
if (region[&"bounds"] as Rect2).intersects(cabin[&"rect"]):
|
||||
blocked = true
|
||||
break
|
||||
if not blocked:
|
||||
return region
|
||||
var world: Variant = _service(&"world_service")
|
||||
var facilities: Variant = _service(&"facility_service")
|
||||
var footprint: Array = model[&"shaft_footprint"]
|
||||
var origins: Array = footprint.filter(func(c: Vector3i) -> bool: return c.y == cell.y and c.z == cell.z)
|
||||
origins.sort_custom(func(a: Vector3i, b: Vector3i) -> bool: return absi(a.x-cell.x) < absi(b.x-cell.x) or (absi(a.x-cell.x) == absi(b.x-cell.x) and a.x < b.x))
|
||||
var lane: Array[Vector3i] = []
|
||||
for origin: Vector3i in origins:
|
||||
for direction: int in [-1, 1]:
|
||||
for distance: int in range(1, 9):
|
||||
var target := origin + Vector3i(direction*distance, 0, 0)
|
||||
if world == null or footprint.has(target) or not world.is_walkable(target):
|
||||
break
|
||||
var facility: Variant = facilities.get_instance(world.get_occupant(target)) if facilities != null else null
|
||||
if facility != null and facility.definition_id not in [&"guest_corridor", &"service_corridor"]:
|
||||
break
|
||||
if not lane.has(target):
|
||||
lane.append(target)
|
||||
lane.sort_custom(func(a: Vector3i, b: Vector3i) -> bool: return absi(a.x-cell.x) < absi(b.x-cell.x) or (absi(a.x-cell.x) == absi(b.x-cell.x) and a.x < b.x))
|
||||
if lane.is_empty():
|
||||
var anchor := get_cell_rect(cell).position+Vector2(-80, -16)
|
||||
var nearest := INF
|
||||
for badge: Dictionary in model[&"landing_badges"]:
|
||||
var landing: Vector3i = badge[&"cell"]
|
||||
if landing.y == cell.y and landing.z == cell.z and absf(landing.x-cell.x) < nearest:
|
||||
nearest = absf(landing.x-cell.x)
|
||||
anchor = badge[&"at"]
|
||||
return {&"bounds": region[&"bounds"], &"transit": false, &"no_lane": true, &"badge_at": anchor}
|
||||
var selected: Vector3i = lane[0]
|
||||
for target: Vector3i in lane:
|
||||
if not model[&"queue_positions"].values().has(cell_to_canvas(target)):
|
||||
selected = target
|
||||
break
|
||||
return {&"bounds": get_cell_rect(selected), &"transit": false, &"center": cell_to_canvas(selected)}
|
||||
|
||||
|
||||
func _life_actor_region(row: Dictionary, person: Dictionary, model: Dictionary) -> Dictionary:
|
||||
var key: String = row[&"key"]
|
||||
var cell: Vector3i = person[&"cell"]
|
||||
@@ -1580,10 +1624,13 @@ func _life_actor_region(row: Dictionary, person: Dictionary, model: Dictionary)
|
||||
if model[&"carried_patients"].has(id):
|
||||
for carrier: Dictionary in model[&"staff"]:
|
||||
if carrier[&"id"] == model[&"carried_patients"][id]:
|
||||
result = _life_track_region("staff/"+String(carrier[&"id"]), carrier[&"cell"], model)
|
||||
result = _life_actor_region({&"key": "staff/"+String(carrier[&"id"]), &"staff": true}, carrier, model)
|
||||
var rect: Rect2 = result[&"bounds"]
|
||||
rect = rect.grow(p)
|
||||
rect.position.y -= 12*p
|
||||
result[&"bounds"] = rect
|
||||
if result.has(&"center"):
|
||||
result[&"center"] -= Vector2(0, 12*p)
|
||||
elif model[&"resting_staff"].has(id):
|
||||
facility_id = model[&"resting_staff"][id]
|
||||
elif model[&"treated_patients"].has(id):
|
||||
@@ -1600,6 +1647,8 @@ func _life_actor_region(row: Dictionary, person: Dictionary, model: Dictionary)
|
||||
var cells: Array[Vector3i] = world.get_entity_cells(facility_id)
|
||||
if not cells.is_empty():
|
||||
result = {&"bounds": _cell_bounds_rect(cells), &"transit": false}
|
||||
if not model[&"queue_positions"].has(key) and not result.has(&"center") and not result.get(&"no_lane", false):
|
||||
result = _life_landing_region(result, cell, model)
|
||||
result[&"bounds"] = (result[&"bounds"] as Rect2).grow(-p)
|
||||
return result
|
||||
|
||||
@@ -1680,6 +1729,7 @@ func _fit_life_actors(model: Dictionary) -> void:
|
||||
for person: Dictionary in model[&"staff"]:
|
||||
people["staff/"+String(person[&"id"])] = person
|
||||
var members: Array = []
|
||||
var stranded: Array = []
|
||||
var all_rows: Array = model[&"actor_drawings"].duplicate()
|
||||
var passenger_bounds: Dictionary = {}
|
||||
for cabin: Dictionary in model[&"cabins"]:
|
||||
@@ -1690,12 +1740,35 @@ func _fit_life_actors(model: Dictionary) -> void:
|
||||
var person: Dictionary = people[row[&"key"]]
|
||||
row[&"cell"] = person[&"cell"]
|
||||
var region := _life_actor_region(row, person, model) if not row[&"riding"] else {&"bounds": passenger_bounds[row[&"key"]], &"transit": false}
|
||||
if region.has(&"center"):
|
||||
var jitter := Vector2.ZERO
|
||||
if not model[&"carried_patients"].has(person[&"id"]):
|
||||
var track: Dictionary = model[&"actor_tracks"][row[&"key"]]
|
||||
var t := 1.0 if model[&"paused"] else clampf((_animation_time-float(track[&"at"]))/0.42, 0, 1)
|
||||
jitter = row[&"center"]-cell_to_canvas(track[&"from"]).lerp(cell_to_canvas(person[&"cell"]), t)
|
||||
row[&"center"] = region[&"center"]+jitter
|
||||
row.merge(_life_scaled(row, row[&"scale"]), true)
|
||||
region[&"row"] = row
|
||||
if not region[&"transit"]:
|
||||
if region.get(&"no_lane", false):
|
||||
stranded.append(region)
|
||||
elif not region[&"transit"]:
|
||||
members.append(region)
|
||||
var groups := _life_fitted_groups(members)
|
||||
model[&"actor_aggregations"] = []
|
||||
var hidden: Dictionary = {}
|
||||
for member: Dictionary in stranded:
|
||||
var row: Dictionary = member[&"row"]
|
||||
hidden[row[&"key"]] = true
|
||||
var aggregate: Dictionary = {}
|
||||
for existing: Dictionary in model[&"actor_aggregations"]:
|
||||
if existing[&"at"] == member[&"badge_at"]:
|
||||
aggregate = existing
|
||||
break
|
||||
if aggregate.is_empty():
|
||||
aggregate = {&"members": [], &"drawn_keys": [], &"at": member[&"badge_at"], &"text": ""}
|
||||
model[&"actor_aggregations"].append(aggregate)
|
||||
aggregate[&"members"].append({&"key": row[&"key"], &"id": people[row[&"key"]][&"id"], &"state": row[&"state"], &"cell": row[&"cell"], &"mode": row[&"mode"]})
|
||||
aggregate[&"text"] = "+%d" % aggregate[&"members"].size()
|
||||
for group: Array in groups:
|
||||
group.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a[&"row"][&"center"].x < b[&"row"][&"center"].x or (a[&"row"][&"center"].x == b[&"row"][&"center"].x and a[&"row"][&"key"] < b[&"row"][&"key"]))
|
||||
var base := 1.0
|
||||
|
||||
Reference in New Issue
Block a user