#!/usr/bin/perl use strict; use warnings; use perllib::Iff; # Things to look for: # # object templates # forceNoCollision # # appearance templtaes # FORM 0003 # Extents # NULL collision extent means not collideable # 1163416400 - EXSP # 1163412056 - EXBX # 1480808780 - XCYL # 1129140308 - CMPT # 1146372428 - DTAL # 1129141064 - CMSH # 1314212940 - NULL # # Path: # objectTemplate (probably have to go up heirarchy / shared) # - scan for forceNoCollision # - scan for appearanceTemplate (server side) # appearanceTemplate # - scan for ssa # serverSideAppearance # - scan for collision extent use constant DEBUG => 1; use constant UNTESTED => -1; use constant NOT_COLLIDEABLE => 0; use constant COLLIDEABLE => 1; sub usage { die "\n\tfindAllCollideableObjects.pl \n\n"; } usage if (!@ARGV); my $branch = shift; my $branchDir = ""; open (P4, "p4 -ztag where //depot/swg/$branch/... |") || die "Can't run p4 where for $branch\n"; while () { $branchDir = $1 if (m!\.\.\. path (\S+)[\\\/]\.\.\.!); } close (P4); $branchDir =~ s![\\\/]+!/!g; my %appearanceTemplates; my %objectTemplates; print "\nBuilding list of all object templates...\n"; open (P4, "p4 files //depot/swg/$branch/dsrc/*/sys.s*/compiled/game/object/... |") || die "Can't run p4 files for $branch\n"; while () { next if (/ - delete/); chomp; s!\#.*$!!; # element maps to : [ , ] my $path = $_; $path =~ s!//depot/swg/$branch/!$branchDir/!; $_ =~ s!^.*/dsrc/sku[^\\\/]+/sys[^\\\/]+/compiled/game/!!; $objectTemplates{$_} = [$path, UNTESTED]; } close (P4); print "\nBuilding list of all appearance files...\n"; open (P4, "p4 files //depot/swg/$branch/data/*/sys.*/.../appearance/... |") || die "Can't run p4 files for $branch\n"; while () { next if (/ - delete/); chomp; s!\#.*$!!; my $path = $_; $path =~ s!//depot/swg/$branch/!$branchDir/!; $_ =~ s!^.*/data/sku[^\\\/]+/sys[^\\\/]+/[^\\\/]+/[^\\\/]+/!!; $appearanceTemplates{$_} = [$path, UNTESTED]; } close (P4); print "\nScanning all object templates...\n"; foreach my $objectTemplate (sort keys %objectTemplates) { # skip this element if we've tested it next if ($objectTemplates{$objectTemplate}->[1] != UNTESTED); if ($objectTemplate =~ m!/base/! || $objectTemplate =~ m!/base/!) { print "$objectTemplate : not collideable : because it's a base object\n" if (DEBUG); $objectTemplates{$objectTemplate}->[1] = NOT_COLLIDEABLE; next; } if ($objectTemplate =~ m!\.(btm)|(me)|(txt)!) { print "$objectTemplate : not collideable : because it's a file I don't care about\n" if (DEBUG); $objectTemplates{$objectTemplate}->[1] = NOT_COLLIDEABLE; next; } my $collideable = UNTESTED; my $analyzingObjectTemplate = $objectTemplate; my $debugTabs = ""; while ($collideable == UNTESTED) { my $forceNoCollision = 0; my $appearanceTemplate = ""; my $baseObjectTemplate = ""; my $sharedObjectTemplate = ""; my $portalLayoutFile = ""; if (DEBUG) { print "${debugTabs}Scanning $analyzingObjectTemplate...\n"; $debugTabs .= "\t"; } my $analyzingObjectTemplateDisk = $objectTemplates{$analyzingObjectTemplate}->[0]; open (OT, $analyzingObjectTemplateDisk) || die "Can't open $analyzingObjectTemplateDisk\n"; while () { $baseObjectTemplate = $1 if (m/^\s*\@base\s+(\S+)/i); $forceNoCollision = 1 if (m/^\s*forceNoCollision\s*=\s*true/i); $appearanceTemplate = $1 if (m/^\s*appearanceFilename\s*=\s*\"(\S+)\"/i); $sharedObjectTemplate = $1 if (m/^\s*(?:crafted)?sharedTemplate\s*=\s*\"(\S+)\"/i); $portalLayoutFile = $1 if (m/^\s*portalLayoutFilename\s*=\s*\"(\S+)\"/i); } close (OT); if ($forceNoCollision) { print "$objectTemplate : not collideable : forceNoCollision specified\n" if (DEBUG); $collideable = NOT_COLLIDEABLE; last; } if ($portalLayoutFile) { print "$objectTemplate : collideable : portal layout found\n" if (DEBUG); $collideable = COLLIDEABLE; last; } if ($appearanceTemplate) { my $appearanceTemplateDisk = (exists $appearanceTemplates{$appearanceTemplate}) ? $appearanceTemplates{$appearanceTemplate}->[0] : ""; if ($appearanceTemplateDisk =~ m!/sys\.client/!) { print "$objectTemplate : not collideable : appearance is client side only\n" if (DEBUG); $collideable = NOT_COLLIDEABLE; last; } else { print "${debugTabs}Scanning appearance $appearanceTemplate...\n" if (DEBUG); if ($appearanceTemplateDisk) { my $appearanceFileHandle; open ($appearanceFileHandle, $appearanceTemplateDisk) || die "Can't open $appearanceTemplateDisk\n"; my $iff = Iff->createFromFileHandle($appearanceFileHandle); close ($appearanceFileHandle); # Handle Iff contents. my $name = $iff->getCurrentName(); if ($name eq "APT " && $iff->isCurrentForm()) { $iff->enterForm(); $name = $iff->getCurrentName(); if ($name eq "0000" && $iff->isCurrentForm()) { $iff->enterForm(); $name = $iff->getCurrentName(); if ($name eq "NAME" && !$iff->isCurrentForm()) { $iff->enterChunk(); my $ssaFileName = $iff->read_string(); print "${debugTabs}Scanning ssa $ssaFileName...\n" if (DEBUG); my $ssaFileNameDisk = (exists $appearanceTemplates{$ssaFileName}) ? $appearanceTemplates{$ssaFileName}->[0] : ""; if ($ssaFileNameDisk) { my $ssaFileHandle; open ($ssaFileHandle, $ssaFileNameDisk) || die "Can't open $ssaFileNameDisk\n"; $iff = Iff->createFromFileHandle($ssaFileHandle); close ($ssaFileHandle); # Handle Iff contents my $name = $iff->getCurrentName(); if ($name eq "APPR" && $iff->isCurrentForm()) { $iff->enterForm(); $name = $iff->getCurrentName(); if ($name eq "0003" && $iff->isCurrentForm()) { $iff->enterForm(); # enter / exit past extent block $iff->enterForm(); $iff->exitForm(); # we should now be pointing to the collision property form $name = $iff->getCurrentName(); if ($name eq "NULL") { # enter / exit past collision property block $iff->enterForm(); $iff->exitForm(); # enter / exit past hardpoint block $iff->enterForm(); $iff->exitForm(); $name = $iff->getCurrentName(); if ($name eq "FLOR" && $iff->isCurrentForm()) { $iff->enterForm(); $name = $iff->getCurrentName(); if ($name eq "DATA" && !$iff->isCurrentForm()) { $iff->enterChunk(); my $hasFloor = $iff->read_uint8(); if ($hasFloor == 0) { print "$objectTemplate : not collideable : null collision property and null floor\n" if (DEBUG); $collideable = NOT_COLLIDEABLE; } else { print "$objectTemplate : collideable : non-null floor\n" if (DEBUG); $collideable = COLLIDEABLE; } } } } else { print "$objectTemplate : collideable : non-null collision property\n" if (DEBUG); $collideable = COLLIDEABLE; } } else { # for all other forms of this piece of data, we assume not collideable print "$objectTemplate : not collideable : null collision property\n" if (DEBUG); $collideable = NOT_COLLIDEABLE; } } } } } } # if we got here and didn't get a solution, default to collideable if ($collideable == UNTESTED) { print "$objectTemplate : collideable : couldn't get appearance template info\n" if (DEBUG); $collideable = COLLIDEABLE; last; } } } } $sharedObjectTemplate =~ s!\.iff!\.tpf!; $baseObjectTemplate =~ s!\.iff!\.tpf!; if (!$sharedObjectTemplate || !exists $objectTemplates{$sharedObjectTemplate}) { if (!$baseObjectTemplate || !exists $objectTemplates{$baseObjectTemplate}) { print "$objectTemplate : collideable : no base, no shared, no appearance specified, defaulting\n" if (DEBUG); $collideable = COLLIDEABLE; last; } else { $sharedObjectTemplate = ""; } } $analyzingObjectTemplate = ($sharedObjectTemplate) ? $sharedObjectTemplate : $baseObjectTemplate; } $objectTemplates{$objectTemplate}->[1] = $collideable; } print "\nPrinting out object templates with collision...\n"; foreach my $template (sort keys %objectTemplates) { print "$template\n" if ($objectTemplates{$template}->[1] == COLLIDEABLE && $template !~ /shared_/); }