@@ -360,46 +360,115 @@ function isObjectType(obj,typ)
360360 return false
361361 end
362362
363+ --- ShipTemplateBasedObject-derived types
364+ -- STBOs typically require a ship template applied with setTemplate().
365+ -- These conditions might fail if no template is applied, especially for
366+ -- SpaceStations
363367 if typ == " SpaceStation" then
364- return obj .components .docking_bay and obj .components .physics and obj .components .physics .type == " static"
368+ return obj .components .docking_bay
369+ and obj .components .physics
370+ and obj .components .physics .type == " static"
365371 elseif typ == " PlayerSpaceship" then
366372 return obj .components .player_control
367- elseif typ == " ScanProbe" then
368- return obj .components .allow_radar_link
369373 elseif typ == " CpuShip" then
370374 return obj .components .ai_controller
375+ --- Probes
376+ elseif typ == " ScanProbe" then
377+ return obj .components .allow_radar_link
378+ --- Terrain
379+ -- Asteroids are uniquely identified by having Spin, AvoidObject, and
380+ -- ExplodeOnTouch. Missiles don't Spin and Mines use DelayedExplodeOnTouch
371381 elseif typ == " Asteroid" then
372- return obj .components .mesh_render and string.sub (obj .components .mesh_render .mesh , 1 , 7 ) == " Astroid" and obj .components .physics
382+ return obj .components .spin
383+ and obj .components .avoid_object
384+ and obj .components .explode_on_touch
385+ -- VisualAsteroids lack physics or avoid_object. This can match a false
386+ -- positive for non-asteroid decorative objects, but are there any that
387+ -- didn't use either VisualAsteroid or Planet?
373388 elseif typ == " VisualAsteroid" then
374- return obj .components .mesh_render and string.sub (obj .components .mesh_render .mesh , 1 , 7 ) == " Astroid" and not obj .components .physics
375- elseif typ == " Artifact" then
376- return obj .components .mesh_render and string.sub (obj .components .mesh_render .mesh , 1 , 13 ) == " mesh/Artifact"
389+ return obj .components .spin
390+ and obj .components .mesh_render
391+ and not obj .components .physics
392+ and not obj .components .avoid_object
377393 elseif typ == " Nebula" then
378394 return obj .components .nebula_renderer
379395 elseif typ == " Planet" then
380396 return obj .components .planet_render
381- elseif typ == " SupplyDrop" then
382- return obj .components .pickup and obj .components .radar_trace and obj .components .radar_trace .icon == " radar/blip.png" and obj .components .radar_trace .color_by_faction
383397 elseif typ == " BlackHole" then
384- return obj .components .gravity and obj .components .billboard_render and obj .components .billboard_render .texture == " blackHole3d.png"
398+ return obj .components .gravity
399+ and obj .components .billboard_render
400+ and obj .components .gravity .damage
401+ -- All Gravity components have a default wormhole_target of {0,0}, so
402+ -- wormholes are distinguished from black holes primarily by not dealing
403+ -- damage or pointing to {0,0}. A wormhole pointing to {0,0} therefore won't
404+ -- be detected as a wormhole.
405+ elseif typ == " WormHole" then
406+ return obj .components .gravity
407+ and obj .components .billboard_render
408+ and not obj .components .gravity .damage
409+ and (obj .components .gravity .wormhole_target [1 ] ~= 0 or obj .components .gravity .wormhole_target [2 ] ~= 0 )
410+ --- Items
411+ -- Artifact check is fragile because its mesh filename doesn't need to
412+ -- contain `mesh/Artifact`.
413+ elseif typ == " Artifact" then
414+ return obj .components .mesh_render
415+ and string.sub (obj .components .mesh_render .mesh , 1 , 13 ) == " mesh/Artifact"
416+ -- A SupplyDrop must carry at least one supply, distinguishing it from an
417+ -- Artifact with allowPickup(true). This check therefore doesn't match a
418+ -- SupplyDrop that doesn't have any supplies.
419+ elseif typ == " SupplyDrop" then
420+ return obj .components .pickup
421+ and (obj .components .pickup .give_energy > 0
422+ or obj .components .pickup .give_homing > 0
423+ or obj .components .pickup .give_nuke > 0
424+ or obj .components .pickup .give_mine > 0
425+ or obj .components .pickup .give_emp > 0
426+ or obj .components .pickup .give_hvli > 0 )
427+ --- Countermeasures
385428 elseif typ == " WarpJammer" then
386429 return obj .components .warp_jammer
430+ --- Weapons
431+ -- Launched mines have missile_flight, scripted mines don't, so that
432+ -- unintuitively isn't checked for the Mine type
387433 elseif typ == " Mine" then
388- return obj .components .delayed_explode_on_touch and obj .components .constant_particle_emitter
434+ return obj .components .delayed_explode_on_touch
435+ and obj .components .constant_particle_emitter
436+ -- HVLIs lack homing, HomingMissiles lack ExplodeOnTimeout, Nukes lack EMP
437+ -- damage
389438 elseif typ == " EMPMissile" then
390- return obj .components .radar_trace and obj .components .radar_trace .icon == " radar/missile.png" and obj .components .explode_on_touch and obj .components .explode_on_touch .damage_type == " emp"
439+ return obj .components .missile_flight
440+ and obj .components .missile_homing
441+ and obj .components .explode_on_timeout
442+ and obj .components .explode_on_touch
443+ and obj .components .explode_on_touch .damage_type == " emp"
391444 elseif typ == " Nuke" then
392- return obj .components .radar_trace and obj .components .radar_trace .icon == " radar/missile.png" and obj .components .explode_on_touch and obj .components .explode_on_touch .explosion_sfx == " sfx/nuke_explosion.wav"
393- elseif typ == " Zone" then
394- return obj .components .zone
395- elseif typ == " WormHole" then
396- return obj .components .gravity and obj .components .billboard_render and obj .components .billboard_render .texture == " wormHole3d.png"
397- elseif typ == " BeamEffect" then
398- return obj .components .beam_effect
445+ return obj .components .missile_flight
446+ and obj .components .missile_homing
447+ and obj .components .explode_on_timeout
448+ and obj .components .explode_on_touch
449+ and obj .components .explode_on_touch .damage_type ~= " emp"
399450 elseif typ == " HomingMissile" then
400- return obj .components .explode_on_touch and obj .components .radar_trace and obj .components .radar_trace .color [3 ] == 0
451+ return obj .components .missile_flight
452+ and obj .components .missile_homing
453+ and obj .components .explode_on_touch
454+ and not obj .components .explode_on_timeout
401455 elseif typ == " HVLI" then
402- return obj .components .explode_on_touch and obj .components .radar_trace and obj .components .radar_trace .color [1 ] == 200
456+ return obj .components .missile_flight
457+ and not obj .components .missile_homing
458+ and obj .components .explode_on_touch
459+ and not obj .components .explode_on_timeout
460+ --- Weapon effects
461+ elseif typ == " ExplosionEffect" then
462+ return obj .components .explosion_effect
463+ and not obj .components .explosion_effect .electrical
464+ elseif typ == " ElectricExplosionEffect" then
465+ return obj .components .explosion_effect
466+ and obj .components .explosion_effect .electrical
467+ elseif typ == " BeamEffect" then
468+ return obj .components .beam_effect
469+ --- Data
470+ elseif typ == " Zone" then
471+ return obj .components .zone
403472 elseif typ == " ScienceDatabase" then
404473 return obj .components .science_database
405474 elseif typ == " FactionInfo" then
0 commit comments