Merge branch 'master' into qt-sdl

Conflicts:
	macosx/Warzone.xcodeproj/project.pbxproj
master
Per Inge Mathisen 2011-12-17 16:02:26 +01:00
commit 700bb7a56e
130 changed files with 2113 additions and 1165 deletions

View File

@ -1,14 +1,14 @@
270 400 0 100 _("CAMPAIGN ONE") 270 400 0.0 4.0 _("CAMPAIGN ONE")
260 420 0 100 _("WESTERN SECTOR") 260 420 0.0 4.0 _("WESTERN SECTOR")
20 20 101 399 _("Dawn, July 4th, 2100") 20 20 4.04 15.96 _("Dawn, July 4th, 2100")
0 0 101 399 _("Project HQ") 0 0 4.04 15.96 _("Project HQ")
0 0 101 399 _("A New Era") 0 0 4.04 15.96 _("A New Era")
20 20 499 799 _("Morning, July 4th, 2100") 20 20 19.96 31.96 _("Morning, July 4th, 2100")
0 0 499 799 _("In-flight to Western Sector") 0 0 19.96 31.96 _("In-flight to Western Sector")
0 0 499 799 _("Team Alpha nears its destination") 0 0 19.96 31.96 _("Team Alpha nears its destination")
20 20 1250 1725 _("OBJECTIVE: Locate and recover neural synapse technology") 20 20 50.0 69.0 _("OBJECTIVE: Locate and recover neural synapse technology")
20 447 1250 1725 _("Establish a base, then search for a Pre-Collapse structure.") 20 447 50.0 69.0 _("Establish a base, then search for a Pre-Collapse structure.")
0 0 1250 1725 _("This structure contains technology vital for the success of the Project.") 0 0 50.0 69.0 _("This structure contains technology vital for the success of the Project.")

View File

@ -1,12 +1,12 @@
20 432 100 200 _("Transport destinations follow:") 20 432 4.0 8.0 _("Transport destinations follow:")
0 0 100 200 _("Alpha - Western Sector....") 0 0 4.0 8.0 _("Alpha - Western Sector....")
20 432 225 350 _("Alpha you are cleared for take-off.") 20 432 9.0 14.0 _("Alpha you are cleared for take-off.")
0 0 225 350 _("Good luck and good hunting.") 0 0 9.0 14.0 _("Good luck and good hunting.")
20 432 750 875 _("Approaching Landing Zone. Team Alpha Briefing commences.") 20 432 30.0 35.0 _("Approaching Landing Zone. Team Alpha Briefing commences.")
20 432 925 1150 _("Commander, you lead Team Alpha, one of three expeditionary teams sent out by the Project to recover artifacts from before the Collapse.") 20 432 37.0 46.0 _("Commander, you lead Team Alpha, one of three expeditionary teams sent out by the Project to recover artifacts from before the Collapse.")
20 432 1175 1240 _("Your destination lies in the western zone.") 20 432 47.0 49.6 _("Your destination lies in the western zone.")

View File

@ -1,7 +1,7 @@
20 20 0 60 _("Incoming Transmission") 20 20 0.0 2.4 _("Incoming Transmission")
20 20 70 250 _("Transmission from Beta Base") 20 20 2.8 10.0 _("Transmission from Beta Base")
20 452 70 250 _("Mayday! Mayday!") 20 452 2.8 10.0 _("Mayday! Mayday!")
0 0 70 250 _("Please assist!...") 0 0 2.8 10.0 _("Please assist!...")
20 20 730 844 _("Commander you are to assist Team Beta") 20 20 29.2 33.76 _("Commander you are to assist Team Beta")

View File

@ -1,11 +1,11 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 0 100 _("Commander, we have recovered a command turret from the New Paradigm.") 20 432 0.0 4.0 _("Commander, we have recovered a command turret from the New Paradigm.")
20 432 125 375 _("This turret allows commanders to coordinate attacks between assigned units and to act as a delivery point for factories. Researching and using this technology has the highest priority.") 20 432 5.0 15.0 _("This turret allows commanders to coordinate attacks between assigned units and to act as a delivery point for factories. Researching and using this technology has the highest priority.")
20 432 425 475 _("Commander, we are receiving this transmission.") 20 432 17.0 19.0 _("Commander, we are receiving this transmission.")

View File

@ -1,5 +1,5 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 150 325 _("Your attacks upon us will not go unpunished.") 20 432 6.0 13.0 _("Your attacks upon us will not go unpunished.")
0 0 150 325 _("You are in contravention of the New Paradigm.") 0 0 6.0 13.0 _("You are in contravention of the New Paradigm.")

View File

@ -1,9 +1,9 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 200 370 _("All attack groups commence attack on enemy.") 20 432 8.0 14.8 _("All attack groups commence attack on enemy.")
0 0 200 370 _("They are in contravention of the New Paradigm.") 0 0 8.0 14.8 _("They are in contravention of the New Paradigm.")
20 432 385 450 _("They must be eradicated.") 20 432 15.4 18.0 _("They must be eradicated.")

View File

@ -1,8 +1,8 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 25 175 _("Secure the LZ and establish a forward base.") 20 432 1.0 7.0 _("Secure the LZ and establish a forward base.")
0 0 25 175 _("Then destroy the New Paradigm's base.") 0 0 1.0 7.0 _("Then destroy the New Paradigm's base.")

View File

@ -1,10 +1,10 @@
20 432 150 325 _("Open your systems to me.") 20 432 6.0 13.0 _("Open your systems to me.")
0 0 150 325 _("Let me meld with your machines and cyborgs.") 0 0 6.0 13.0 _("Let me meld with your machines and cyborgs.")
20 432 330 550 _("We will create the perfect nexus of man and machine.") 20 432 13.2 22.0 _("We will create the perfect nexus of man and machine.")
0 0 330 550 _("Together we can create a new world.") 0 0 13.2 22.0 _("Together we can create a new world.")
20 432 575 675 _("I can give you power beyond your wildest dreams.") 20 432 23.0 27.0 _("I can give you power beyond your wildest dreams.")
20 432 700 925 _("Open your systems to me and you will be strong.") 20 432 28.0 37.0 _("Open your systems to me and you will be strong.")
0 0 700 925 _("I can raise you as gods upon the blasted earth.") 0 0 28.0 37.0 _("I can raise you as gods upon the blasted earth.")

View File

@ -1,6 +1,6 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 25 125 _("When we failed to respond it became threatening.") 20 432 1.0 5.0 _("When we failed to respond it became threatening.")

View File

@ -1,6 +1,6 @@
20 432 75 337 _("Your interference in my plans for the New Paradigm will not go unpunished.") 20 432 3.0 13.48 _("Your interference in my plans for the New Paradigm will not go unpunished.")
0 0 75 337 _("You are weak flesh-things. I am strong and have many parts.") 0 0 3.0 13.48 _("You are weak flesh-things. I am strong and have many parts.")
20 432 350 600 _("You may defeat me here, but I shall rise again.") 20 432 14.0 24.0 _("You may defeat me here, but I shall rise again.")
0 0 350 600 _("As I once cleansed the world with fire, I will destroy you and your puny Project!!") 0 0 14.0 24.0 _("As I once cleansed the world with fire, I will destroy you and your puny Project!!")

View File

@ -1,13 +1,13 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 25 190 _("Nexus then removed itself from the system, destroying its memory banks, and removing all traces of its external connections.") 20 432 1.0 7.6 _("Nexus then removed itself from the system, destroying its memory banks, and removing all traces of its external connections.")
20 432 200 475 _("We are not sure what Nexus is or who or what is directing it. Initial research links the Nexus Intruder Program with the Reed Corporation, the developer of the synaptic link.") 20 432 8.0 19.0 _("We are not sure what Nexus is or who or what is directing it. Initial research links the Nexus Intruder Program with the Reed Corporation, the developer of the synaptic link.")
20 432 500 710 _("We have ascertained that Nexus supplied the New Paradigm with most of its technology. Whatever Nexus is, it's more than a computer parasite.") 20 432 20.0 28.4 _("We have ascertained that Nexus supplied the New Paradigm with most of its technology. Whatever Nexus is, it's more than a computer parasite.")
20 432 725 900 _("It has technology and weapons. It knows about us, and it's not friendly.") 20 432 29.0 36.0 _("It has technology and weapons. It knows about us, and it's not friendly.")

View File

@ -1,16 +1,16 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 65 190 _("The Synaptic Link was developed by the Reed Corporation in conjunction with the US Military.") 20 432 2.6 7.6 _("The Synaptic Link was developed by the Reed Corporation in conjunction with the US Military.")
20 432 200 550 _("The synaptic link allows for almost instantaneous transfer of thought from human operators to vehicle control and guidance systems. The synaptic link is fitted into the base of the skull circling the spinal column.") 20 432 8.0 22.0 _("The synaptic link allows for almost instantaneous transfer of thought from human operators to vehicle control and guidance systems. The synaptic link is fitted into the base of the skull circling the spinal column.")
20 432 625 750 _("The link has a hi-speed data transfer port that plugs into any computer system.") 20 432 25.0 30.0 _("The link has a hi-speed data transfer port that plugs into any computer system.")
20 432 925 1200 _("More importantly the development of the synaptic link made the creation of cyborgs possible. Early attempts at power suits for individual soldiers failed as they proved to be slow and unresponsive.") 20 432 37.0 48.0 _("More importantly the development of the synaptic link made the creation of cyborgs possible. Early attempts at power suits for individual soldiers failed as they proved to be slow and unresponsive.")
20 432 1350 1700 _("The synaptic link allowed soldiers to be placed in power suits that they controlled as easily as their own bodies. Power suits allowed infantry to function effectively on the battlefields of the 21st Century.") 20 432 54.0 68.0 _("The synaptic link allowed soldiers to be placed in power suits that they controlled as easily as their own bodies. Power suits allowed infantry to function effectively on the battlefields of the 21st Century.")
20 432 1715 1925 _("Unfortunately, this technology has fallen into the hands of the New Paradigm. It is imperative that you research and develop synaptic link technologies.") 20 432 68.6 77.0 _("Unfortunately, this technology has fallen into the hands of the New Paradigm. It is imperative that you research and develop synaptic link technologies.")

View File

@ -1,12 +1,12 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 200 275 _("Warning!") 20 432 8.0 11.0 _("Warning!")
0 0 200 275 _("You are entering a restricted area.") 0 0 8.0 11.0 _("You are entering a restricted area.")
20 432 300 550 _("Return to your designated zone or be destroyed.") 20 432 12.0 22.0 _("Return to your designated zone or be destroyed.")
0 0 300 550 _("Repeat. Return to your designated zone or be destroyed.") 0 0 12.0 22.0 _("Repeat. Return to your designated zone or be destroyed.")
0 0 300 550 _("Message Ends.") 0 0 12.0 22.0 _("Message Ends.")

View File

@ -1,9 +1,9 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 200 370 _("Your attacks upon us will not go unpunished.") 20 432 8.0 14.8 _("Your attacks upon us will not go unpunished.")
0 0 200 370 _("You are in contravention of the New Paradigm.") 0 0 8.0 14.8 _("You are in contravention of the New Paradigm.")
20 432 380 440 _("You will be destroyed.") 20 432 15.2 17.6 _("You will be destroyed.")

View File

@ -1,7 +1,7 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 210 380 _("NEXUS, the synaptic technology you required has been recovered and sent for collection.") 20 432 8.4 15.2 _("NEXUS, the synaptic technology you required has been recovered and sent for collection.")

View File

@ -1,15 +1,15 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 75 275 _("This Nexus Intruder Program is a self-mutating computer parasite. This makes it difficult to eradicate from systems once it has been identified.") 20 432 3.0 11.0 _("This Nexus Intruder Program is a self-mutating computer parasite. This makes it difficult to eradicate from systems once it has been identified.")
20 432 300 735 _("We have been unable to ascertain it's ultimate goal or function. In its initial form it seeks out and isolates sections of memory from the rest of the invaded system. It then begins to mutate itself and data structures, effectively reprogramming the system from within.") 20 432 12.0 29.4 _("We have been unable to ascertain it's ultimate goal or function. In its initial form it seeks out and isolates sections of memory from the rest of the invaded system. It then begins to mutate itself and data structures, effectively reprogramming the system from within.")
20 432 750 960 _("Further analysis was prevented by the manual shutdown of the system by our technicians to prevent additional contamination by the Nexus Intruder Program.") 20 432 30.0 38.4 _("Further analysis was prevented by the manual shutdown of the system by our technicians to prevent additional contamination by the Nexus Intruder Program.")
20 432 975 1225 _("However, the spread of the Nexus Intruder Program was not checked by New Paradigm. We need to capture New Paradigm's core systems to further investigate Nexus and determine its origins.") 20 432 39.0 49.0 _("However, the spread of the Nexus Intruder Program was not checked by New Paradigm. We need to capture New Paradigm's core systems to further investigate Nexus and determine its origins.")
20 432 1250 1425 _("Commander, you are to curtail the New Paradigm's activities in this sector and locate their main base.") 20 432 50.0 57.0 _("Commander, you are to curtail the New Paradigm's activities in this sector and locate their main base.")

View File

@ -1,8 +1,8 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 150 375 _("You have done well.") 20 432 6.0 15.0 _("You have done well.")
0 0 150 375 _("Once we have analyzed and authenticated the technology, your reward will follow.") 0 0 6.0 15.0 _("Once we have analyzed and authenticated the technology, your reward will follow.")

View File

@ -1,7 +1,7 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 432 25 190 _("Information discovered at the previous enemy base indicates that the New Paradigm recovered two synaptic link artifacts.") 20 432 2.08333333333 15.8333333333 _("Information discovered at the previous enemy base indicates that the New Paradigm recovered two synaptic link artifacts.")

View File

@ -1,18 +1,18 @@
270 400 0 100 _("CAMPAIGN TWO") 270 400 0.0 8.33333333333 _("CAMPAIGN TWO")
265 420 0 100 _("EASTERN SECTOR") 265 420 0.0 8.33333333333 _("EASTERN SECTOR")
20 20 105 285 _("Morning, September 1st, 2100") 20 20 8.75 23.75 _("Morning, September 1st, 2100")
0 0 105 285 _("In-flight to Eastern Sector") 0 0 8.75 23.75 _("In-flight to Eastern Sector")
0 0 105 285 _("Team Alpha approaches Beta Base") 0 0 8.75 23.75 _("Team Alpha approaches Beta Base")
20 20 320 912 _("BETA BASE MISSION: Eastern Sector") 20 20 26.6666666667 76.0 _("BETA BASE MISSION: Eastern Sector")
20 447 320 912 _("Upon arrival you are to assume command of the base.") 20 447 26.6666666667 76.0 _("Upon arrival you are to assume command of the base.")
0 0 320 912 _("You must defend and hold it at all costs.") 0 0 26.6666666667 76.0 _("You must defend and hold it at all costs.")
270 465 925 1125 _("THE COLLECTIVE") 270 465 77.0833333333 93.75 _("THE COLLECTIVE")
20 20 1730 1770 _("BETA BASE MISSION: Eastern Sector") 20 20 144.166666667 147.5 _("BETA BASE MISSION: Eastern Sector")
20 20 1800 2127 _("BETA BASE MISSION: Defend and Fortify") 20 20 150.0 177.25 _("BETA BASE MISSION: Defend and Fortify")
20 447 1800 2127 _("Be sure to fortify the perimeter and establish anti-aircraft defenses.") 20 447 150.0 177.25 _("Be sure to fortify the perimeter and establish anti-aircraft defenses.")
0 0 1800 2127 _("New technologies are available.") 0 0 150.0 177.25 _("New technologies are available.")

View File

@ -1,6 +1,6 @@
20 432 40 200 _("Commander, a new launch has been detected.") 20 432 1.6 8.0 _("Commander, a new launch has been detected.")
0 0 40 200 _("It is likely to be targeted at your location.") 0 0 1.6 8.0 _("It is likely to be targeted at your location.")
20 432 220 385 _("You are to start the immediate evacuation of Beta Base to the safe haven.") 20 432 8.8 15.4 _("You are to start the immediate evacuation of Beta Base to the safe haven.")

View File

@ -1,28 +1,28 @@
20 432 0 125 _("NASDA is the North American Strategic Defense Agency.") 20 432 0.0 10.4166666667 _("NASDA is the North American Strategic Defense Agency.")
20 432 150 435 _("NASDA was formed in 2076 to defend North America from conventional and nuclear attack. The construction of a satellite defense system began in 2081 and was completed in 2082.") 20 432 12.5 36.25 _("NASDA was formed in 2076 to defend North America from conventional and nuclear attack. The construction of a satellite defense system began in 2081 and was completed in 2082.")
20 432 450 590 _("In 2085 the NASDA satellites fired their nukes at Earth.") 20 432 37.5 49.1666666667 _("In 2085 the NASDA satellites fired their nukes at Earth.")
20 432 635 800 _("There were also ground-based sites. Many of these were destroyed in the nuclear counterstrikes, but there's bound to be some out there.") 20 432 52.9166666667 66.6666666667 _("There were also ground-based sites. Many of these were destroyed in the nuclear counterstrikes, but there's bound to be some out there.")
20 432 825 1000 _("The NASDA satellites also contained pulse-lasers designed to shoot down missiles approaching North America.") 20 432 68.75 83.3333333333 _("The NASDA satellites also contained pulse-lasers designed to shoot down missiles approaching North America.")
20 432 85.8333333333 106.25 _("During the counterstrikes, these LasSats failed to fire. If brought into operation, these LasSats could inflict major damage on ground targets.")
20 432 108.333333333 118.333333333 _("All nukes targeted at North America found their targets.")
20 447 119.166666667 141.666666667 _("We know that Nexus is searching for NASDA Central in the Eastern Sector. This was one of the land-based control centres for the satellites.")
20 453 142.5 147.083333333 _("If the centre is found intact, NEXUS may gain control of the satellites.")
20 432 148.333333333 154.166666667 _("Nexus claimed that it had already destroyed the world.")
20 432 1030 1275 _("During the counterstrikes, these LasSats failed to fire. If brought into operation, these LasSats could inflict major damage on ground targets.")
20 432 1300 1420 _("All nukes targeted at North America found their targets.")
20 447 1430 1700 _("We know that Nexus is searching for NASDA Central in the Eastern Sector. This was one of the land-based control centres for the satellites.")
20 453 1710 1765 _("If the centre is found intact, NEXUS may gain control of the satellites.")
20 432 1780 1850 _("Nexus claimed that it had already destroyed the world.")

View File

@ -1,2 +1,2 @@
20 432 25 150 _("NASDA Briefing follows...") 20 432 2.08333333333 12.5 _("NASDA Briefing follows...")

View File

@ -1,4 +1,4 @@
20 432 10 100 _("We've got to make sure that it can't do it again.") 20 432 0.4 4.0 _("We've got to make sure that it can't do it again.")

View File

@ -1,9 +1,9 @@
20 432 20 200 _("Analysis indicates that these systems were part of the control system for the NASDA satellites.") 20 432 1.66666666667 16.6666666667 _("Analysis indicates that these systems were part of the control system for the NASDA satellites.")
0 0 20 200 _("It's now certain that Nexus was responsible for The Collapse.") 0 0 1.66666666667 16.6666666667 _("It's now certain that Nexus was responsible for The Collapse.")
20 432 220 500 _("During the early stages of the Collapse, NASDA technicians switched off the infected systems in order to isolate the spread of Nexus. This seems to have prevented the LasSats from firing during the counterstrikes.") 20 432 18.3333333333 41.6666666667 _("During the early stages of the Collapse, NASDA technicians switched off the infected systems in order to isolate the spread of Nexus. This seems to have prevented the LasSats from firing during the counterstrikes.")
20 432 520 825 _("The ensuing nuclear-magnetic pulses wiped clean large amounts of NASDA's memory banks, shattering its core processor, and sent shockwaves blasting through Nexus.") 20 432 43.3333333333 68.75 _("The ensuing nuclear-magnetic pulses wiped clean large amounts of NASDA's memory banks, shattering its core processor, and sent shockwaves blasting through Nexus.")
20 432 875 1000 _("Nexus was fried as whole sections of its consciousness were obliterated in the counterstrikes.") 20 432 72.9166666667 83.3333333333 _("Nexus was fried as whole sections of its consciousness were obliterated in the counterstrikes.")

View File

@ -1,6 +1,6 @@
20 432 40 175 _("Commander we are detecting transmissions from this site that are reaching high orbit.") 20 432 1.6 7.0 _("Commander we are detecting transmissions from this site that are reaching high orbit.")
20 432 325 410 _("Nexus has now reconnected itself with the NASDA satellites.") 20 432 13.0 16.4 _("Nexus has now reconnected itself with the NASDA satellites.")
20 432 420 565 _("This poses a major threat to the Project and to our survival.") 20 432 16.8 22.6 _("This poses a major threat to the Project and to our survival.")

View File

@ -1,6 +1,6 @@
20 432 25 190 _("Analysis of NASDA Central leaves no doubt that The Collective has introduced the Nexus Intruder Virus to it.") 20 432 1.0 7.6 _("Analysis of NASDA Central leaves no doubt that The Collective has introduced the Nexus Intruder Virus to it.")
20 432 210 350 _("The nuclear reactor was going to be used to power a vast network of pre-Collapse computer systems.") 20 432 8.4 14.0 _("The nuclear reactor was going to be used to power a vast network of pre-Collapse computer systems.")

View File

@ -1,6 +1,6 @@
20 432 25 100 _("Commander, we have just detected a missile launch at these coordinates.") 20 432 2.08333333333 8.33333333333 _("Commander, we have just detected a missile launch at these coordinates.")
20 432 125 260 _("Team Gamma are sending a team to investigate the launch site and to prevent any further launches.") 20 432 10.4166666667 21.6666666667 _("Team Gamma are sending a team to investigate the launch site and to prevent any further launches.")
20 432 270 565 _("We can only assume that Nexus has gained control of this site. We cannot determine whether the missile is nuclear-armed or where it is targeted. You are advised to begin preparations for the evacuation of your base.") 20 432 22.5 47.0833333333 _("We can only assume that Nexus has gained control of this site. We cannot determine whether the missile is nuclear-armed or where it is targeted. You are advised to begin preparations for the evacuation of your base.")

View File

@ -1,5 +1,5 @@
20 432 225 425 _("Warriors of the Collective, I seek the location of NASDA Central.") 20 432 9.0 17.0 _("Warriors of the Collective, I seek the location of NASDA Central.")
0 0 225 425 _("It lies somewhere in your territory.") 0 0 9.0 17.0 _("It lies somewhere in your territory.")
20 432 450 635 _("Find it for me and I shall provide you with further weapons to aid you in your war against the Project.") 20 432 18.0 25.4 _("Find it for me and I shall provide you with further weapons to aid you in your war against the Project.")

View File

@ -1 +1 @@
20 432 10 325 _("As I once cleansed the world with fire, I will destroy you and your puny Project!!") 20 432 0.4 13.0 _("As I once cleansed the world with fire, I will destroy you and your puny Project!!")

View File

@ -1,8 +1,8 @@
20 432 25 290 _("Warriors of The Collective, more intruders are entering our territory.") 20 432 2.08333333333 24.1666666667 _("Warriors of The Collective, more intruders are entering our territory.")
0 0 25 290 _("They are not part of the machine.") 0 0 2.08333333333 24.1666666667 _("They are not part of the machine.")
20 432 300 625 _("Warriors of The Collective, attack and destroy kill all who resist the machine.") 20 432 25.0 52.0833333333 _("Warriors of The Collective, attack and destroy kill all who resist the machine.")
0 0 300 625 _("Attack! Erase their presence from this area!") 0 0 25.0 52.0833333333 _("Attack! Erase their presence from this area!")

View File

@ -1,11 +1,11 @@
20 432 25 250 _("Warriors of The Collective, we are ready to destroy the intruders who pollute our lands.") 20 432 2.08333333333 20.8333333333 _("Warriors of The Collective, we are ready to destroy the intruders who pollute our lands.")
20 432 275 625 _("Those of the Project are not of the machine. They have been denied its blessing. We who have embraced the power of the machine have a destiny to sweep away such weak creatures.") 20 432 22.9166666667 52.0833333333 _("Those of the Project are not of the machine. They have been denied its blessing. We who have embraced the power of the machine have a destiny to sweep away such weak creatures.")
20 432 650 775 _("They shall fall before the might of The Collective.") 20 432 54.1666666667 64.5833333333 _("They shall fall before the might of The Collective.")
20 432 800 925 _("Attack and destroy all who resist the machine.") 20 432 66.6666666667 77.0833333333 _("Attack and destroy all who resist the machine.")
0 0 800 925 _("Attack!") 0 0 66.6666666667 77.0833333333 _("Attack!")

View File

@ -1,6 +1,6 @@
20 432 10 320 _("Warriors of the Collective, Nexus has given us the power of the machine so that we can destroy all that oppose us.") 20 432 0.833333333333 26.6666666667 _("Warriors of the Collective, Nexus has given us the power of the machine so that we can destroy all that oppose us.")
20 432 325 500 _("Nexus now asks us to crush the Project.") 20 432 27.0833333333 41.6666666667 _("Nexus now asks us to crush the Project.")
0 0 325 500 _("Cleanse and destroy!!") 0 0 27.0833333333 41.6666666667 _("Cleanse and destroy!!")

View File

@ -1,8 +1,8 @@
20 432 240 380 _("Warriors of the Collective. You have performed well.") 20 432 9.6 15.2 _("Warriors of the Collective. You have performed well.")
0 0 240 380 _("Your just reward is on its way.") 0 0 9.6 15.2 _("Your just reward is on its way.")
20 432 390 525 _("The Project is fleeing its base and stealing your technology.") 20 432 15.6 21.0 _("The Project is fleeing its base and stealing your technology.")
0 0 390 525 _("You must stop them!") 0 0 15.6 21.0 _("You must stop them!")

View File

@ -1,4 +1,4 @@
20 432 10 100 _("Decoding Transmission...") 20 432 0.4 4.0 _("Decoding Transmission...")

View File

@ -1,17 +1,17 @@
260 400 0 100 _("CAMPAIGN THREE") 260 400 0.0 8.33333333333 _("CAMPAIGN THREE")
254 420 0 100 _("NORTHERN SECTOR") 254 420 0.0 8.33333333333 _("NORTHERN SECTOR")
20 20 113 479 _("TRANSPORT MISSION: Northern Sector") 20 20 9.41666666667 39.9166666667 _("TRANSPORT MISSION: Northern Sector")
20 447 113 479 _("Congratulations on your successful evacuation of Beta Base.") 20 447 9.41666666667 39.9166666667 _("Congratulations on your successful evacuation of Beta Base.")
0 0 113 479 _("NEXUS has gained access to nuclear weapons and is determined to destroy the Project.") 0 0 9.41666666667 39.9166666667 _("NEXUS has gained access to nuclear weapons and is determined to destroy the Project.")
20 20 1000 1225 _("Dusk, December 3rd, 2100") 20 20 83.3333333333 102.083333333 _("Dusk, December 3rd, 2100")
0 0 1000 1225 _("In-flight to Northern Sector") 0 0 83.3333333333 102.083333333 _("In-flight to Northern Sector")
0 0 1000 1225 _("The Final Encounter") 0 0 83.3333333333 102.083333333 _("The Final Encounter")
20 20 1278 1338 _("Briefing Commences") 20 20 106.5 111.5 _("Briefing Commences")
20 20 1347 1768 _("TRANSPORT MISSION: Northern Sector") 20 20 112.25 147.333333333 _("TRANSPORT MISSION: Northern Sector")
20 447 1347 1768 _("Once at the mountains secure an LZ. Then establish a forward base.") 20 447 112.25 147.333333333 _("Once at the mountains secure an LZ. Then establish a forward base.")
0 0 1347 1768 _("Team Gamma will contact you there.") 0 0 112.25 147.333333333 _("Team Gamma will contact you there.")

View File

@ -1,7 +1,7 @@
20 432 850 1025 _("Personnel at Gamma Base have confirmed that the nuclear missiles targeted at Alpha and Beta bases were launched from a silo in their sector.") 20 432 70.8333333333 85.4166666667 _("Personnel at Gamma Base have confirmed that the nuclear missiles targeted at Alpha and Beta bases were launched from a silo in their sector.")
20 432 1150 1250 _("Team Gamma is currently scouting the silo's location and monitoring NEXUS's activity.") 20 432 95.8333333333 104.166666667 _("Team Gamma is currently scouting the silo's location and monitoring NEXUS's activity.")
20 432 1275 1350 _("Commander, the success of the Project lies with you.") 20 432 106.25 112.5 _("Commander, the success of the Project lies with you.")

View File

@ -1,4 +1,4 @@
20 432 140 210 _("Time's up commander!!") 20 432 5.6 8.4 _("Time's up commander!!")

View File

@ -1,4 +1,4 @@
20 432 10 175 _("Commander, we are detecting NEXUS forces from these coordinates...") 20 432 0.4 7.0 _("Commander, we are detecting NEXUS forces from these coordinates...")

View File

@ -1,10 +1,10 @@
20 432 0 60 _("Glad you could make it, Commander.") 20 432 0.0 5.0 _("Glad you could make it, Commander.")
20 432 70 235 _("Enemy strike VTOLs have got us pinned down. We've managed to hold off cyborgs and tanks, but we haven't been able to make any progress along the valley.") 20 432 5.83333333333 19.5833333333 _("Enemy strike VTOLs have got us pinned down. We've managed to hold off cyborgs and tanks, but we haven't been able to make any progress along the valley.")
20 432 245 275 _("Can you try and reach us with anti-aircraft units?") 20 432 20.4166666667 22.9166666667 _("Can you try and reach us with anti-aircraft units?")

View File

@ -1,11 +1,11 @@
20 432 20 180 _("This is Team Alpha. Repeat, this is Team Alpha. We require immediate assistance.") 20 432 0.8 7.2 _("This is Team Alpha. Repeat, this is Team Alpha. We require immediate assistance.")
20 432 190 300 _("We are under heavy attack from cyborgs, laser tanks, and strike VTOLs.") 20 432 7.6 12.0 _("We are under heavy attack from cyborgs, laser tanks, and strike VTOLs.")
20 432 315 450 _("We were trying to reach your position, but have been ambushed.") 20 432 12.6 18.0 _("We were trying to reach your position, but have been ambushed.")
0 0 315 450 _("We're holed up in a valley at these coordinates.") 0 0 12.6 18.0 _("We're holed up in a valley at these coordinates.")
0 0 315 450 _("Please assist.") 0 0 12.6 18.0 _("Please assist.")

View File

@ -1,4 +1,4 @@
20 432 20 85 _("Coordinate Download Completed.") 20 432 0.8 3.4 _("Coordinate Download Completed.")
20 432 90 200 _("Commander, forces from Team Alpha escaped the nuclear attack on Alpha Base.") 20 432 3.6 8.0 _("Commander, forces from Team Alpha escaped the nuclear attack on Alpha Base.")

View File

@ -1,6 +1,6 @@
20 432 20 110 _("We are experiencing some interference from NEXUS.") 20 432 0.8 4.4 _("We are experiencing some interference from NEXUS.")
20 432 115 220 _("You must destroy his command centre before we lose control of key systems.") 20 432 4.6 8.8 _("You must destroy his command centre before we lose control of key systems.")

View File

@ -1,4 +1,4 @@
20 432 120 250 _("Commander, welcome to NEXUS!") 20 432 4.8 10.0 _("Commander, welcome to NEXUS!")

View File

@ -1,13 +1,13 @@
20 432 75 250 _("Well done Commander, you've prevented my last missile from launching.") 20 432 3.0 10.0 _("Well done Commander, you've prevented my last missile from launching.")
0 0 75 250 _("Such a shame. Your Project HQ would have made a wonderful target.") 0 0 3.0 10.0 _("Such a shame. Your Project HQ would have made a wonderful target.")
20 432 275 320 _("But it's good of you to join me here.") 20 432 11.0 12.8 _("But it's good of you to join me here.")
20 432 325 425 _("Buried beneath this silo is a tactical nuclear warhead that is set to go off soon.") 20 432 13.0 17.0 _("Buried beneath this silo is a tactical nuclear warhead that is set to go off soon.")
20 432 475 550 _("As I cannot launch it, it'll just have to blow where it is.") 20 432 19.0 22.0 _("As I cannot launch it, it'll just have to blow where it is.")
20 432 560 650 _("Please note that all entrances to the underground complex have been sealed. Goodbye, Commander.") 20 432 22.4 26.0 _("Please note that all entrances to the underground complex have been sealed. Goodbye, Commander.")

View File

@ -1,15 +1,15 @@
20 432 75 165 _("Ah, Commander, so good of you to join us here at Nexus base.") 20 432 3.0 6.6 _("Ah, Commander, so good of you to join us here at Nexus base.")
20 432 175 320 _("It was very useful having Gamma Team set up here in the mountains.") 20 432 7.0 12.8 _("It was very useful having Gamma Team set up here in the mountains.")
0 0 175 320 _("Their absorption was such a pleasure.") 0 0 7.0 12.8 _("Their absorption was such a pleasure.")
20 432 325 400 _("Thank you for all those useful technologies you've recovered.") 20 432 13.0 16.0 _("Thank you for all those useful technologies you've recovered.")
20 432 405 510 _("You and not those fools in the New Paradigm and the Collective.") 20 432 16.2 20.4 _("You and not those fools in the New Paradigm and the Collective.")
20 432 530 620 _("I'm now activating all your synaptic links so that your forces can meld with Nexus.") 20 432 21.2 24.8 _("I'm now activating all your synaptic links so that your forces can meld with Nexus.")
20 432 630 720 _("Your forces are now mine! Welcome to Nexus.") 20 432 25.2 28.8 _("Your forces are now mine! Welcome to Nexus.")
//_(" for me. Had I known you'd be so useful, I'd have hired ") //_(" for me. Had I known you'd be so useful, I'd have hired ")

View File

@ -1,14 +1,14 @@
20 432 75 220 _("Commander, you're proving to be more resilient than I thought.") 20 432 3.0 8.8 _("Commander, you're proving to be more resilient than I thought.")
0 0 75 220 _("Such a pity that you refused to join me earlier.") 0 0 3.0 8.8 _("Such a pity that you refused to join me earlier.")
20 432 225 300 _("But no matter, as you'll not be here much longer.") 20 432 9.0 12.0 _("But no matter, as you'll not be here much longer.")
20 432 325 425 _("After much searching and reprogramming, I've finally got all my systems back on-line.") 20 432 13.0 17.0 _("After much searching and reprogramming, I've finally got all my systems back on-line.")
20 432 450 700 _("Once I destroyed the world with nuclear fire to clear the way for my cybernetic future.") 20 432 18.0 28.0 _("Once I destroyed the world with nuclear fire to clear the way for my cybernetic future.")
0 0 450 700 _("I now intend to further shape the world into my own image, by surgically removing unwanted growths like yourself.") 0 0 18.0 28.0 _("I now intend to further shape the world into my own image, by surgically removing unwanted growths like yourself.")
20 432 725 850 _("My Laser Satellites are now powering up. I intend to test them on you first, Commander!") 20 432 29.0 34.0 _("My Laser Satellites are now powering up. I intend to test them on you first, Commander!")

View File

@ -1,20 +1,20 @@
20 432 0 200 _("The Reed Corporation was founded by Dr Allan Reed. In 2080, Dr Reed landed a contract with the US Military to develop the synaptic link technology.") 20 432 0.0 16.6666666667 _("The Reed Corporation was founded by Dr Allan Reed. In 2080, Dr Reed landed a contract with the US Military to develop the synaptic link technology.")
20 432 225 350 _("After patenting the synaptic link five years later, Dr Reed continued his researches into cybernetics.") 20 432 18.75 29.1666666667 _("After patenting the synaptic link five years later, Dr Reed continued his researches into cybernetics.")
20 432 375 600 _("His goal this time was to allow transfer of human consciousness into data streams that could meld with computer technologies. While in Cyberspace the operator's bodies were kept in immersion tanks.") 20 432 31.25 50.0 _("His goal this time was to allow transfer of human consciousness into data streams that could meld with computer technologies. While in Cyberspace the operator's bodies were kept in immersion tanks.")
20 432 625 850 _("Backed again by the military, Dr Reed began work on the NEXUS Intruder Program. After three years with little progress, the military abandoned the Nexus Project and cut Dr Reed's funding.") 20 432 52.0833333333 70.8333333333 _("Backed again by the military, Dr Reed began work on the NEXUS Intruder Program. After three years with little progress, the military abandoned the Nexus Project and cut Dr Reed's funding.")
20 432 875 1000 _("Reports from the time claim that Dr Reed was furious and vowed to have his revenge on all who got in his way.") 20 432 72.9166666667 83.3333333333 _("Reports from the time claim that Dr Reed was furious and vowed to have his revenge on all who got in his way.")
20 432 1025 1225 _("It appears that Dr Reed may have succeeded in his goals and completed the Nexus Intruder Program.") 20 432 85.4166666667 102.083333333 _("It appears that Dr Reed may have succeeded in his goals and completed the Nexus Intruder Program.")
0 0 1025 1225 _("The similarity between NEXUS and Dr Reed is striking.") 0 0 85.4166666667 102.083333333 _("The similarity between NEXUS and Dr Reed is striking.")
20 432 1290 1485 _("Such an interesting history lesson. Now allow me to bring you up to date.") 20 432 107.5 123.75 _("Such an interesting history lesson. Now allow me to bring you up to date.")
0 0 1290 1485 _("The NEXUS Intruder Program was created in order to control fools like you.") 0 0 107.5 123.75 _("The NEXUS Intruder Program was created in order to control fools like you.")
20 432 1490 1760 _("It's very simple for me to infiltrate your systems and take them over. It's so simple, in fact, that you wouldn't even know I'm there. That is until I activate parts of myself etched into your core systems.") 20 432 124.166666667 146.666666667 _("It's very simple for me to infiltrate your systems and take them over. It's so simple, in fact, that you wouldn't even know I'm there. That is until I activate parts of myself etched into your core systems.")
20 432 1770 1850 _("Let's start by activating NEXUS in your core systems and see what happens!") 20 432 147.5 154.166666667 _("Let's start by activating NEXUS in your core systems and see what happens!")

View File

@ -1,5 +1,5 @@
20 432 25 200 _("Commander, we are experiencing interference with our equipment.") 20 432 1.0 8.0 _("Commander, we are experiencing interference with our equipment.")
0 0 25 200 _("Normal service will be restored as soon as possible.") 0 0 1.0 8.0 _("Normal service will be restored as soon as possible.")

View File

@ -1,9 +1,9 @@
20 432 75 165 _("Not long to go now, Commander. There's no where else for you to run to.") 20 432 3.0 6.6 _("Not long to go now, Commander. There's no where else for you to run to.")
20 432 210 325 _("However, if you vacate this facility, then I shall let you go free, as you are no longer a threat to me.") 20 432 8.4 13.0 _("However, if you vacate this facility, then I shall let you go free, as you are no longer a threat to me.")
20 432 350 425 _("You have five minutes to comply or else it's frying time!") 20 432 14.0 17.0 _("You have five minutes to comply or else it's frying time!")

View File

@ -1,6 +1,6 @@
20 432 20 150 _("Commander, we are under attack by NEXUS cyborgs and tanks. Please help as we....") 20 432 0.8 6.0 _("Commander, we are under attack by NEXUS cyborgs and tanks. Please help as we....")
20 432 225 360 _("...cannot hold out much longer. Repeat, please help, we cannot hold out much longer....") 20 432 9.0 14.4 _("...cannot hold out much longer. Repeat, please help, we cannot hold out much longer....")

View File

@ -1,18 +1,18 @@
//pos frame //pos frame
//x y start end Text //x y start end Text
20 20 0 550 _("Dusk, November 3rd, 2085") 20 20 0.0 22.0 _("Dusk, November 3rd, 2085")
0 0 0 550 _("Earth, High Orbit") 0 0 0.0 22.0 _("Earth, High Orbit")
0 0 0 550 _("The Collapse") 0 0 0.0 22.0 _("The Collapse")
20 20 975 1450 _("January 19th, 2086") 20 20 39.0 58.0 _("January 19th, 2086")
0 0 975 1450 _("North America") 0 0 39.0 58.0 _("North America")
0 0 975 1450 _("Nuclear Winter") 0 0 39.0 58.0 _("Nuclear Winter")
20 20 1500 2000 _("Midnight, April 10th, 2086") 20 20 60.0 80.0 _("Midnight, April 10th, 2086")
0 0 1500 2000 _("Rocky Mountains") 0 0 60.0 80.0 _("Rocky Mountains")
0 0 1500 2000 _("Safety") 0 0 60.0 80.0 _("Safety")
20 20 2300 4000 _("Dawn, April 4th, 2100") 20 20 92.0 160.0 _("Dawn, April 4th, 2100")
0 0 2300 4000 _("North America") 0 0 92.0 160.0 _("North America")
0 0 2300 4000 _("A New Beginning") 0 0 92.0 160.0 _("A New Beginning")

View File

@ -1,22 +1,22 @@
20 432 0 250 _("The NASDA system was developed to protect us. It was to be the ultimate nuclear deterrent. As it turned out, it was our executioner.") 20 432 0.0 10.0 _("The NASDA system was developed to protect us. It was to be the ultimate nuclear deterrent. As it turned out, it was our executioner.")
20 432 275 550 _("Reports said that NASDA developed a fault during a routine systems check. Don't believe it. Someone wanted it to take us out.") 20 432 11.0 22.0 _("Reports said that NASDA developed a fault during a routine systems check. Don't believe it. Someone wanted it to take us out.")
20 432 625 985 _("Those nukes were targeted on every major city around the world. NASDA was programmed to start the Collapse. When the counterstrikes launched, its laser defenses and anti-missile ground sites failed.") 20 432 25.0 39.4 _("Those nukes were targeted on every major city around the world. NASDA was programmed to start the Collapse. When the counterstrikes launched, its laser defenses and anti-missile ground sites failed.")
20 432 1010 1125 _("The world as we knew it ended...") 20 432 40.4 45.0 _("The world as we knew it ended...")
20 432 1150 1475 _("The Nuclear Winter hit hard. Disease and famine claimed most of us who had survived the nuclear strikes. Wars over cans of dog food took even more.") 20 432 46.0 59.0 _("The Nuclear Winter hit hard. Disease and famine claimed most of us who had survived the nuclear strikes. Wars over cans of dog food took even more.")
20 432 1500 1650 _("We'd fled Seattle early in '86. We'd heard that the Rocky Mountains were relatively rad-free.") 20 432 60.0 66.0 _("We'd fled Seattle early in '86. We'd heard that the Rocky Mountains were relatively rad-free.")
20 432 1675 1950 _("After fighting off bands of marauders we came across the base. Its personnel were dead. Killed by any one of a number of virulent diseases.") 20 432 67.0 78.0 _("After fighting off bands of marauders we came across the base. Its personnel were dead. Killed by any one of a number of virulent diseases.")
20 432 1975 2200 _("We cracked the doors, and cleared out the bodies inside.") 20 432 79.0 88.0 _("We cracked the doors, and cleared out the bodies inside.")
20 432 2225 2560 _("We knew that things would never be the same again, but we were determined to build a new world out of the ruins. We rebuilt the landing pads and brought the old systems back on-line.") 20 432 89.0 102.4 _("We knew that things would never be the same again, but we were determined to build a new world out of the ruins. We rebuilt the landing pads and brought the old systems back on-line.")
20 432 2600 2750 _("We were finally ready to begin the Project.") 20 432 104.0 110.0 _("We were finally ready to begin the Project.")

View File

@ -1,10 +1,10 @@
20 432 500 610 _("After many long months of struggle, we defeated NEXUS.") 20 432 41.6666666667 50.8333333333 _("After many long months of struggle, we defeated NEXUS.")
20 432 620 710 _("The war started by Dr Reed was over.") 20 432 51.6666666667 59.1666666667 _("The war started by Dr Reed was over.")
20 432 720 810 _("We have recovered many of the technologies we sought.") 20 432 60.0 67.5 _("We have recovered many of the technologies we sought.")
20 432 820 930 _("It is now time to use them to rebuild the world.") 20 432 68.3333333333 77.5 _("It is now time to use them to rebuild the world.")
20 432 940 1100 _("Slowly, out of the ashes we will rise again...") 20 432 78.3333333333 91.6666666667 _("Slowly, out of the ashes we will rise again...")

View File

@ -32,6 +32,10 @@
#include <time.h> #include <time.h>
// Maximum seconds per frame.
// If not reaching the goal, force graphics updates, even if we aren't doing enough game state updates to maintain game speed.
#define MAXIMUM_SPF 1/4
/* See header file for documentation */ /* See header file for documentation */
UDWORD gameTime = 0, deltaGameTime = 0, graphicsTime = 0, deltaGraphicsTime = 0, realTime = 0, deltaRealTime = 0; UDWORD gameTime = 0, deltaGameTime = 0, graphicsTime = 0, deltaGraphicsTime = 0, realTime = 0, deltaRealTime = 0;
float graphicsTimeFraction = 0.0, realTimeFraction = 0.0; float graphicsTimeFraction = 0.0, realTimeFraction = 0.0;
@ -188,10 +192,10 @@ void gameTimeUpdate()
{ {
unsigned player; unsigned player;
// Pause time, since we are waiting GAME_GAME_TIME from other players. // Pause time at current game time, since we are waiting GAME_GAME_TIME from other players.
scaledCurrTime = graphicsTime; scaledCurrTime = gameTime;
baseTime = currTime; baseTime = currTime;
timeOffset = graphicsTime; timeOffset = gameTime;
debug(LOG_SYNC, "Waiting for other players. gameTime = %u, player times are {%s}", gameTime, listToString("%u", ", ", gameQueueTime, gameQueueTime + game.maxPlayers).c_str()); debug(LOG_SYNC, "Waiting for other players. gameTime = %u, player times are {%s}", gameTime, listToString("%u", ", ", gameQueueTime, gameQueueTime + game.maxPlayers).c_str());
mayUpdate = false; mayUpdate = false;
@ -212,10 +216,10 @@ void gameTimeUpdate()
// Adjust deltas. // Adjust deltas.
if (scaledCurrTime >= gameTime && mayUpdate) if (scaledCurrTime >= gameTime && mayUpdate)
{ {
if (scaledCurrTime > gameTime + GAME_TICKS_PER_UPDATE) if (scaledCurrTime > gameTime + GAME_TICKS_PER_SEC*MAXIMUM_SPF)
{ {
// Game isn't updating fast enough... // Game isn't updating fast enough...
uint32_t slideBack = deltaGraphicsTime - GAME_TICKS_PER_UPDATE; uint32_t slideBack = deltaGraphicsTime - GAME_TICKS_PER_SEC*MAXIMUM_SPF;
baseTime += slideBack / modifier; // adjust the addition to base time baseTime += slideBack / modifier; // adjust the addition to base time
deltaGraphicsTime -= slideBack; deltaGraphicsTime -= slideBack;
} }
@ -235,6 +239,11 @@ void gameTimeUpdate()
deltaGameTime = 0; deltaGameTime = 0;
} }
if (deltaGameTime != 0)
{
deltaGraphicsTime = 0; // Don't update graphics until game state is updated.
}
// Store the game and graphics times // Store the game and graphics times
gameTime += deltaGameTime; gameTime += deltaGameTime;
graphicsTime += deltaGraphicsTime; graphicsTime += deltaGraphicsTime;

View File

@ -224,7 +224,6 @@ static bool ReadPoints( const char **ppFileData, iIMDShape *s )
static bool _imd_load_points( const char **ppFileData, iIMDShape *s ) static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
{ {
Vector3f *p = NULL; Vector3f *p = NULL;
int32_t tempXMax, tempXMin, tempZMax, tempZMin;
int32_t xmax, ymax, zmax; int32_t xmax, ymax, zmax;
double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new; double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new;
double xspan, yspan, zspan, maxspan; double xspan, yspan, zspan, maxspan;
@ -247,8 +246,8 @@ static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
return false; return false;
} }
s->max.x = s->max.y = s->max.z = tempXMax = tempZMax = -FP12_MULTIPLIER; s->max.x = s->max.y = s->max.z = -FP12_MULTIPLIER;
s->min.x = s->min.y = s->min.z = tempXMin = tempZMin = FP12_MULTIPLIER; s->min.x = s->min.y = s->min.z = FP12_MULTIPLIER;
vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER; vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER;
vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER; vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER;
@ -265,18 +264,6 @@ static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
s->min.x = p->x; s->min.x = p->x;
} }
/* Biggest x coord so far within our height window? */
if( p->x > tempXMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
{
tempXMax = p->x;
}
/* Smallest x coord so far within our height window? */
if( p->x < tempXMin && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
{
tempXMin = p->x;
}
if (p->y > s->max.y) if (p->y > s->max.y)
{ {
s->max.y = p->y; s->max.y = p->y;
@ -295,18 +282,6 @@ static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
s->min.z = p->z; s->min.z = p->z;
} }
/* Biggest z coord so far within our height window? */
if( p->z > tempZMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
{
tempZMax = p->z;
}
/* Smallest z coord so far within our height window? */
if( p->z < tempZMax && p->y > DROID_VIS_LOWER && p->y < DROID_VIS_UPPER )
{
tempZMin = p->z;
}
// for tight sphere calculations // for tight sphere calculations
if (p->x < vxmin.x) if (p->x < vxmin.x)
{ {
@ -394,7 +369,6 @@ static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
if (zspan > maxspan) if (zspan > maxspan)
{ {
maxspan = zspan;
dia1 = vzmin; dia1 = vzmin;
dia2 = vzmax; dia2 = vzmax;
} }

View File

@ -980,10 +980,9 @@ void eventFireCallbackTrigger(TRIGGER_TYPE callback)
// Run a trigger // Run a trigger
static bool eventFireTrigger(ACTIVE_TRIGGER *psTrigger) static bool eventFireTrigger(ACTIVE_TRIGGER *psTrigger)
{ {
bool fired; bool fired = false;
INTERP_VAL sResult; INTERP_VAL sResult;
fired = false;
psFiringTrigger = psTrigger; psFiringTrigger = psTrigger;
// If this is a code trigger see if it fires // If this is a code trigger see if it fires

View File

@ -233,13 +233,12 @@ static bool eventLoadContext(WzConfig &ini)
// into the variables data space. // into the variables data space.
if (!eventGetContextVal(psCCont, i, &psVal)) if (!eventGetContextVal(psCCont, i, &psVal))
{ {
debug(LOG_FATAL, "Could not find variable in context"); debug(LOG_FATAL, "Could not find variable %d in context %d", i, context);
return false; return false;
} }
if (!loadFunc(psVal, ini)) if (!loadFunc(psVal, ini))
{ {
debug(LOG_FATAL, "Ccould not get variable value"); debug(LOG_FATAL, "Could not get variable value context %d, variable %d", context, i);
return false; return false;
} }
} }

View File

@ -1045,6 +1045,11 @@ int seq_GetFrameNumber()
return frames; return frames;
} }
double seq_GetFrameTime()
{
return videobuf_time;
}
// this controls the size of the video to display on screen // this controls the size of the video to display on screen
void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY) void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY)
{ {
@ -1083,4 +1088,4 @@ void seq_setScanlineMode(SCANLINE_MODE mode)
SCANLINE_MODE seq_getScanlineMode(void) SCANLINE_MODE seq_getScanlineMode(void)
{ {
return use_scanlines; return use_scanlines;
} }

View File

@ -36,5 +36,6 @@ extern int seq_GetFrameNumber(void);
extern void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY); extern void seq_SetDisplaySize(int sizeX, int sizeY, int posX, int posY);
extern void seq_setScanlineMode(SCANLINE_MODE mode); extern void seq_setScanlineMode(SCANLINE_MODE mode);
extern SCANLINE_MODE seq_getScanlineMode(void); extern SCANLINE_MODE seq_getScanlineMode(void);
double seq_GetFrameTime();
#endif // __INCLUDED_LIB_SEQUENCE_SEQUENCE_H__ #endif // __INCLUDED_LIB_SEQUENCE_SEQUENCE_H__

View File

@ -105,7 +105,7 @@ fi
cd ../../ cd ../../
echo "Copying the app cleanly." echo "Copying the app cleanly."
rm -r -f $dmgout/Warzone.app rm -r -f $dmgout/Warzone.app
if ! tar -c --exclude '.svn' --exclude 'Makefile*' --exclude 'makefile*' --exclude '.DS_Store' -C build/${CONFIGURATION} Warzone.app | tar -xC $dmgout; then if ! tar -c --exclude '*.svg' --exclude 'Makefile*' --exclude 'makefile*' --exclude '.DS_Store' -C build/${CONFIGURATION} Warzone.app | tar -xC $dmgout; then
echo "error: Unable to copy the app" >&2 echo "error: Unable to copy the app" >&2
exit 1 exit 1
fi fi

View File

@ -42,6 +42,7 @@
#include "scriptcb.h" #include "scriptcb.h"
#include "scripttabs.h" #include "scripttabs.h"
#include "transporter.h" #include "transporter.h"
#include "mapgrid.h"
/* attack run distance */ /* attack run distance */
#define VTOL_ATTACK_LENGTH 1000 #define VTOL_ATTACK_LENGTH 1000
@ -314,9 +315,6 @@ void actionAlignTurret(BASE_OBJECT *psObj, int weapon_slot)
uint16_t tRot; uint16_t tRot;
uint16_t tPitch; uint16_t tPitch;
//default turret rotation 0
tRot = 0;
//get the maximum rotation this frame //get the maximum rotation this frame
rotation = gameTimeAdjustedIncrement(DEG(ACTION_TURRET_ROTATION_RATE)); rotation = gameTimeAdjustedIncrement(DEG(ACTION_TURRET_ROTATION_RATE));
@ -678,116 +676,85 @@ static void actionCalcPullBackPoint(BASE_OBJECT *psObj, BASE_OBJECT *psTarget, S
// check whether a droid is in the neighboring tile to a build position // check whether a droid is in the neighboring tile to a build position
bool actionReachedBuildPos(DROID *psDroid, SDWORD x, SDWORD y, BASE_STATS *psStats) bool actionReachedBuildPos(DROID const *psDroid, int x, int y, uint16_t dir, BASE_STATS const *psStats)
{ {
SDWORD width, breadth, tx,ty, dx,dy;
ASSERT_OR_RETURN(false, psStats != NULL && psDroid != NULL, "Bad stat or droid"); ASSERT_OR_RETURN(false, psStats != NULL && psDroid != NULL, "Bad stat or droid");
CHECK_DROID(psDroid); CHECK_DROID(psDroid);
Vector2i size = getStatsSize(psStats, dir);
Vector2i map = map_coord(Vector2i(x, y)) - size/2;
// do all calculations in half tile units so that // do all calculations in half tile units so that
// the droid moves to within half a tile of the target // the droid moves to within half a tile of the target
// NOT ANY MORE - JOHN // NOT ANY MORE - JOHN
dx = map_coord(psDroid->pos.x); Vector2i delta = map_coord(removeZ(psDroid->pos)) - map;
dy = map_coord(psDroid->pos.y); return delta.x >= -1 && delta.x <= size.x && delta.y >= -1 && delta.y <= size.y;
if (StatIsStructure(psStats))
{
width = ((STRUCTURE_STATS *)psStats)->baseWidth;
breadth = ((STRUCTURE_STATS *)psStats)->baseBreadth;
}
else
{
width = ((FEATURE_STATS *)psStats)->baseWidth;
breadth = ((FEATURE_STATS *)psStats)->baseBreadth;
}
tx = map_coord(x);
ty = map_coord(y);
// move the x,y to the top left of the structure
tx -= width/2;
ty -= breadth/2;
if ( (dx == (tx -1)) || (dx == (tx + width)) )
{
// droid could be at either the left or the right
if ( (dy >= (ty -1)) && (dy <= (ty + breadth)) )
{
return true;
}
}
else if ( (dy == (ty -1)) || (dy == (ty + breadth)) )
{
// droid could be at either the top or the bottom
if ( (dx >= (tx -1)) && (dx <= (tx + width)) )
{
return true;
}
}
return false;
} }
// check if a droid is on the foundations of a new building // check if a droid is on the foundations of a new building
static bool actionDroidOnBuildPos(DROID *psDroid, SDWORD x, SDWORD y, BASE_STATS *psStats) static bool actionRemoveDroidsFromBuildPos(unsigned player, Vector2i pos, uint16_t dir, BASE_STATS *psStats)
{ {
SDWORD width, breadth, tx,ty, dx,dy;
CHECK_DROID(psDroid);
ASSERT_OR_RETURN(false, psStats != NULL, "Bad stat"); ASSERT_OR_RETURN(false, psStats != NULL, "Bad stat");
dx = map_coord(psDroid->pos.x); bool buildPosEmpty = true;
dy = map_coord(psDroid->pos.y);
if (StatIsStructure(psStats)) Vector2i size = getStatsSize(psStats, dir);
Vector2i map = map_coord(pos) - size/2;
Vector2i structureCentre = world_coord(map) + world_coord(size)/2;
unsigned structureMaxRadius = iHypot(world_coord(size)/2) + 1; // +1 since iHypot rounds down.
gridStartIterate(structureCentre.x, structureCentre.y, structureMaxRadius);
BASE_OBJECT *psObj;
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{ {
width = ((STRUCTURE_STATS *)psStats)->baseWidth; DROID *droid = castDroid(psObj);
breadth = ((STRUCTURE_STATS *)psStats)->baseBreadth; if (droid == NULL)
}
else
{
width = ((FEATURE_STATS *)psStats)->baseWidth;
breadth = ((FEATURE_STATS *)psStats)->baseBreadth;
}
tx = map_coord(x) - (width / 2);
ty = map_coord(y) - (breadth / 2);
if (dx >= tx
&& dx < tx + width
&& dy >= ty
&& dy < ty + breadth)
{
return true;
}
return false;
}
// return the position of a players home base
// MAY return an invalid (0, 0) position on MP maps!
static void actionHomeBasePos(SDWORD player, SDWORD *px, SDWORD *py)
{
STRUCTURE *psStruct;
ASSERT_OR_RETURN(, player >= 0 && player < MAX_PLAYERS, "Invalid player number %d", (int)player);
for(psStruct = apsStructLists[player]; psStruct; psStruct=psStruct->psNext)
{
if (psStruct->pStructureType->type == REF_HQ)
{ {
*px = (SDWORD)psStruct->pos.x; continue; // Only looking for droids.
*py = (SDWORD)psStruct->pos.y; }
return;
Vector2i delta = map_coord(removeZ(droid->pos)) - map;
if (delta.x < 0 || delta.x >= size.x || delta.y < 0 || delta.y >= size.y)
{
continue; // Droid not under new structure (just near it).
}
buildPosEmpty = false; // Found a droid, have to move it away.
if (!aiCheckAlliances(player, droid->player))
{
continue; // Enemy droids probably don't feel like moving.
}
// TODO If the action code was less convoluted, it would be possible for the droid should drive away instead of just getting moved away.
Vector2i bestDest;
unsigned bestDist = UINT32_MAX;
for (int y = -1; y <= size.y; ++y)
for (int x = -1; x <= size.x; x += y >= 0 && y < size.y? size.x + 1 : 1)
{
Vector2i dest = world_coord(map + Vector2i(x, y)) + Vector2i(TILE_UNITS, TILE_UNITS)/2;
unsigned dist = iHypot(removeZ(droid->pos) - dest);
if (dist < bestDist && !fpathBlockingTile(map_coord(dest.x), map_coord(dest.y), getPropulsionStats(droid)->propulsionType))
{
bestDest = dest;
bestDist = dist;
}
}
if (bestDist != UINT32_MAX)
{
// Push the droid out of the way.
Vector2i newPos = removeZ(droid->pos) + iSinCosR(iAtan2(bestDest - removeZ(droid->pos)), gameTimeAdjustedIncrement(TILE_UNITS));
droidSetPosition(droid, newPos.x, newPos.y);
} }
} }
*px = getLandingX(player); return buildPosEmpty;
*py = getLandingY(player);
} }
void actionSanity(DROID *psDroid) void actionSanity(DROID *psDroid)
{ {
// Don't waste ammo unless given a direct attack order. // Don't waste ammo unless given a direct attack order.
@ -927,7 +894,7 @@ void actionUpdateDroid(DROID *psDroid)
// move back to the repair facility if necessary // move back to the repair facility if necessary
if (DROID_STOPPED(psDroid) && if (DROID_STOPPED(psDroid) &&
!actionReachedBuildPos(psDroid, !actionReachedBuildPos(psDroid,
(SDWORD)psDroid->psTarget->pos.x,(SDWORD)psDroid->psTarget->pos.y, psDroid->psTarget->pos.x, psDroid->psTarget->pos.y, ((STRUCTURE*)psDroid->psTarget)->rot.direction,
((STRUCTURE*)psDroid->psTarget)->pStructureType ) ) ((STRUCTURE*)psDroid->psTarget)->pStructureType ) )
{ {
moveDroidToNoFormation(psDroid, psDroid->psTarget->pos.x, psDroid->psTarget->pos.y); moveDroidToNoFormation(psDroid, psDroid->psTarget->pos.x, psDroid->psTarget->pos.y);
@ -1501,11 +1468,14 @@ void actionUpdateDroid(DROID *psDroid)
break; break;
} }
// moving to a location to build a structure // moving to a location to build a structure
if (actionReachedBuildPos(psDroid, if (actionReachedBuildPos(psDroid, psDroid->orderX, psDroid->orderY, psDroid->orderDirection, psDroid->psTarStats))
(SDWORD)psDroid->orderX,(SDWORD)psDroid->orderY, psDroid->psTarStats) &&
!actionDroidOnBuildPos(psDroid,
(SDWORD)psDroid->orderX,(SDWORD)psDroid->orderY, psDroid->psTarStats))
{ {
bool buildPosEmpty = actionRemoveDroidsFromBuildPos(psDroid->player, Vector2i(psDroid->orderX, psDroid->orderY), psDroid->orderDirection, psDroid->psTarStats);
if (!buildPosEmpty)
{
break;
}
bool helpBuild = false; bool helpBuild = false;
// Got to destination - start building // Got to destination - start building
STRUCTURE_STATS* const psStructStats = (STRUCTURE_STATS*)psDroid->psTarStats; STRUCTURE_STATS* const psStructStats = (STRUCTURE_STATS*)psDroid->psTarStats;
@ -1661,26 +1631,8 @@ void actionUpdateDroid(DROID *psDroid)
} }
else if (DROID_STOPPED(psDroid)) else if (DROID_STOPPED(psDroid))
{ {
if (actionDroidOnBuildPos(psDroid, objTrace(psDroid->id, "DACTION_MOVETOBUILD: Starting to drive toward construction site - move status was %d", (int)psDroid->sMove.Status);
(SDWORD)psDroid->orderX,(SDWORD)psDroid->orderY, psDroid->psTarStats)) moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
{
SDWORD pbx = 0, pby = 0;
actionHomeBasePos(psDroid->player, &pbx, &pby);
if (pbx == 0 || pby == 0)
{
objTrace(psDroid->id, "DACTION_MOVETOBUILD: No HQ, cannot move in that direction");
psDroid->action = DACTION_NONE;
break;
}
objTrace(psDroid->id, "DACTION_MOVETOBUILD: Starting to drive inside construction site");
moveDroidToNoFormation(psDroid, (UDWORD)pbx,(UDWORD)pby);
}
else
{
objTrace(psDroid->id, "DACTION_MOVETOBUILD: Starting to drive toward construction site - move status was %d", (int)psDroid->sMove.Status);
moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
}
} }
break; break;
case DACTION_BUILD: case DACTION_BUILD:
@ -1691,8 +1643,7 @@ void actionUpdateDroid(DROID *psDroid)
break; break;
} }
if (DROID_STOPPED(psDroid) && if (DROID_STOPPED(psDroid) &&
!actionReachedBuildPos(psDroid, !actionReachedBuildPos(psDroid, psDroid->orderX, psDroid->orderY, psDroid->orderDirection, psDroid->psTarStats))
(SDWORD)psDroid->orderX,(SDWORD)psDroid->orderY, psDroid->psTarStats))
{ {
objTrace(psDroid->id, "DACTION_BUILD: Starting to drive toward construction site"); objTrace(psDroid->id, "DACTION_BUILD: Starting to drive toward construction site");
moveDroidToNoFormation(psDroid, psDroid->orderX, psDroid->orderY); moveDroidToNoFormation(psDroid, psDroid->orderX, psDroid->orderY);
@ -1700,8 +1651,7 @@ void actionUpdateDroid(DROID *psDroid)
else if (!DROID_STOPPED(psDroid) && else if (!DROID_STOPPED(psDroid) &&
psDroid->sMove.Status != MOVETURNTOTARGET && psDroid->sMove.Status != MOVETURNTOTARGET &&
psDroid->sMove.Status != MOVESHUFFLE && psDroid->sMove.Status != MOVESHUFFLE &&
actionReachedBuildPos(psDroid, actionReachedBuildPos(psDroid, psDroid->orderX, psDroid->orderY, psDroid->orderDirection, psDroid->psTarStats))
(SDWORD)psDroid->orderX,(SDWORD)psDroid->orderY, psDroid->psTarStats))
{ {
objTrace(psDroid->id, "DACTION_BUILD: Stopped - at construction site"); objTrace(psDroid->id, "DACTION_BUILD: Stopped - at construction site");
moveStopDroid(psDroid); moveStopDroid(psDroid);
@ -1726,8 +1676,7 @@ void actionUpdateDroid(DROID *psDroid)
break; break;
} }
// see if the droid is at the edge of what it is moving to // see if the droid is at the edge of what it is moving to
if (actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, psDroid->psTarStats) && if (actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, ((STRUCTURE *)psDroid->psActionTarget[0])->rot.direction, psDroid->psTarStats))
!actionDroidOnBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, psDroid->psTarStats))
{ {
moveStopDroid(psDroid); moveStopDroid(psDroid);
@ -1749,23 +1698,7 @@ void actionUpdateDroid(DROID *psDroid)
} }
else if (DROID_STOPPED(psDroid)) else if (DROID_STOPPED(psDroid))
{ {
if (actionDroidOnBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, psDroid->psTarStats)) moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
{
SDWORD pbx = 0, pby = 0;
actionHomeBasePos(psDroid->player, &pbx, &pby);
if (pbx == 0 || pby == 0)
{
debug(LOG_NEVER, "No HQ - cannot move in that direction.");
psDroid->action = DACTION_NONE;
break;
}
moveDroidToNoFormation(psDroid, (UDWORD)pbx,(UDWORD)pby);
}
else
{
moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
}
} }
break; break;
@ -1797,7 +1730,7 @@ void actionUpdateDroid(DROID *psDroid)
} }
// now do the action update // now do the action update
if (DROID_STOPPED(psDroid) && !actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, psDroid->psTarStats)) if (DROID_STOPPED(psDroid) && !actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, ((STRUCTURE *)psDroid->psActionTarget[0])->rot.direction, psDroid->psTarStats))
{ {
if (secondaryGetState(psDroid, DSO_HALTTYPE) != DSS_HALT_HOLD || if (secondaryGetState(psDroid, DSO_HALTTYPE) != DSS_HALT_HOLD ||
(psDroid->order != DORDER_NONE && psDroid->order != DORDER_TEMP_HOLD)) (psDroid->order != DORDER_NONE && psDroid->order != DORDER_TEMP_HOLD))
@ -1813,7 +1746,7 @@ void actionUpdateDroid(DROID *psDroid)
else if (!DROID_STOPPED(psDroid) && else if (!DROID_STOPPED(psDroid) &&
psDroid->sMove.Status != MOVETURNTOTARGET && psDroid->sMove.Status != MOVETURNTOTARGET &&
psDroid->sMove.Status != MOVESHUFFLE && psDroid->sMove.Status != MOVESHUFFLE &&
actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, psDroid->psTarStats)) actionReachedBuildPos(psDroid, psDroid->actionPos.x, psDroid->actionPos.y, ((STRUCTURE *)psDroid->psActionTarget[0])->rot.direction, psDroid->psTarStats))
{ {
objTrace(psDroid->id, "Stopped - reached build position"); objTrace(psDroid->id, "Stopped - reached build position");
moveStopDroid(psDroid); moveStopDroid(psDroid);
@ -1838,8 +1771,7 @@ void actionUpdateDroid(DROID *psDroid)
break; break;
case DACTION_MOVETOREPAIRPOINT: case DACTION_MOVETOREPAIRPOINT:
/* moving from front to rear of repair facility or rearm pad */ /* moving from front to rear of repair facility or rearm pad */
if (actionReachedBuildPos(psDroid, psDroid->psActionTarget[0]->pos.x,psDroid->psActionTarget[0]->pos.y, if (actionReachedBuildPos(psDroid, psDroid->psActionTarget[0]->pos.x,psDroid->psActionTarget[0]->pos.y, ((STRUCTURE *)psDroid->psActionTarget[0])->rot.direction, ((STRUCTURE *)psDroid->psActionTarget[0])->pStructureType))
((STRUCTURE *)psDroid->psActionTarget[0])->pStructureType))
{ {
objTrace(psDroid->id, "Arrived at repair point - waiting for our turn"); objTrace(psDroid->id, "Arrived at repair point - waiting for our turn");
moveStopDroid(psDroid); moveStopDroid(psDroid);
@ -2434,21 +2366,7 @@ static void actionDroidBase(DROID *psDroid, DROID_ACTION_DATA *psAction)
psDroid->action = DACTION_MOVETOBUILD; psDroid->action = DACTION_MOVETOBUILD;
psDroid->actionPos.x = psAction->x; psDroid->actionPos.x = psAction->x;
psDroid->actionPos.y = psAction->y; psDroid->actionPos.y = psAction->y;
if (actionDroidOnBuildPos(psDroid, psDroid->orderX, psDroid->orderY, psDroid->psTarStats)) moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
{
actionHomeBasePos(psDroid->player, &pbx,&pby);
if (pbx == 0 || pby == 0)
{
objTrace(psDroid->id, "Setting DACTION_BUILD: No HQ, cannot move in that direction");
psDroid->action = DACTION_NONE;
break;
}
moveDroidToNoFormation(psDroid, (UDWORD)pbx,(UDWORD)pby);
}
else
{
moveDroidToNoFormation(psDroid, psDroid->actionPos.x, psDroid->actionPos.y);
}
break; break;
case DACTION_DEMOLISH: case DACTION_DEMOLISH:
ASSERT(psDroid->order == DORDER_DEMOLISH, ASSERT(psDroid->order == DORDER_DEMOLISH,

View File

@ -90,7 +90,7 @@ bool actionInsideMinRange(DROID *psDroid, BASE_OBJECT *psObj, WEAPON_STATS *psWe
bool actionVisibleTarget(DROID *psDroid, BASE_OBJECT *psTarget, int weapon_slot); bool actionVisibleTarget(DROID *psDroid, BASE_OBJECT *psTarget, int weapon_slot);
/** Check whether a droid is in the neighboring tile to a build position. */ /** Check whether a droid is in the neighboring tile to a build position. */
bool actionReachedBuildPos(DROID *psDroid, SDWORD x, SDWORD y, BASE_STATS *psStats); bool actionReachedBuildPos(DROID const *psDroid, int x, int y, uint16_t direction, BASE_STATS const *psStats);
/** Send the vtol droid back to the nearest rearming pad - if there is one, otherwise return to base. */ /** Send the vtol droid back to the nearest rearming pad - if there is one, otherwise return to base. */
void moveToRearm(DROID *psDroid); void moveToRearm(DROID *psDroid);

View File

@ -116,12 +116,30 @@ struct PathBlockingMap
std::vector<bool> dangerMap; // using threatBits std::vector<bool> dangerMap; // using threatBits
}; };
struct PathNonblockingArea
{
PathNonblockingArea() {}
PathNonblockingArea(StructureTiles const &st) : x1(st.map.x), x2(st.map.x + st.size.x), y1(st.map.y), y2(st.map.y + st.size.y) {}
bool operator ==(PathNonblockingArea const &z) const { return x1 == z.x1 && x2 == z.x2 && y1 == z.y1 && y2 == z.y2; }
bool operator !=(PathNonblockingArea const &z) const { return !(*this == z); }
bool isNonblocking(int x, int y) const
{
return x >= x1 && x < x2 && y >= y1 && y < y2;
}
int16_t x1, x2, y1, y2;
};
// Data structures used for pathfinding, can contain cached results. // Data structures used for pathfinding, can contain cached results.
struct PathfindContext struct PathfindContext
{ {
PathfindContext() : myGameTime(0), iteration(0), blockingMap(NULL) {} PathfindContext() : myGameTime(0), iteration(0), blockingMap(NULL) {}
bool isBlocked(int x, int y) const bool isBlocked(int x, int y) const
{ {
if (srcIgnore.isNonblocking(x, y) || dstIgnore.isNonblocking(x, y))
{
return false; // The path is actually blocked here by a structure, but ignore it since it's where we want to go (or where we came from).
}
// Not sure whether the out-of-bounds check is needed, can only happen if pathfinding is started on a blocking tile (or off the map). // Not sure whether the out-of-bounds check is needed, can only happen if pathfinding is started on a blocking tile (or off the map).
return x < 0 || y < 0 || x >= mapWidth || y >= mapHeight || blockingMap->map[x + y*mapWidth]; return x < 0 || y < 0 || x >= mapWidth || y >= mapHeight || blockingMap->map[x + y*mapWidth];
} }
@ -129,15 +147,17 @@ struct PathfindContext
{ {
return !blockingMap->dangerMap.empty() && blockingMap->dangerMap[x + y*mapWidth]; return !blockingMap->dangerMap.empty() && blockingMap->dangerMap[x + y*mapWidth];
} }
bool matches(PathBlockingMap const *blockingMap_, PathCoord tileS_) const bool matches(PathBlockingMap const *blockingMap_, PathCoord tileS_, PathNonblockingArea srcIgnore_, PathNonblockingArea dstIgnore_) const
{ {
// Must check myGameTime == blockingMap_->type.gameTime, otherwise blockingMap be a deleted pointer which coincidentally compares equal to the valid pointer blockingMap_. // Must check myGameTime == blockingMap_->type.gameTime, otherwise blockingMap could be a deleted pointer which coincidentally compares equal to the valid pointer blockingMap_.
return myGameTime == blockingMap_->type.gameTime && blockingMap == blockingMap_ && tileS == tileS_; return myGameTime == blockingMap_->type.gameTime && blockingMap == blockingMap_ && tileS == tileS_ && srcIgnore == srcIgnore_ && dstIgnore == dstIgnore_;
} }
void assign(PathBlockingMap const *blockingMap_, PathCoord tileS_) void assign(PathBlockingMap const *blockingMap_, PathCoord tileS_, PathNonblockingArea srcIgnore_, PathNonblockingArea dstIgnore_)
{ {
blockingMap = blockingMap_; blockingMap = blockingMap_;
tileS = tileS_; tileS = tileS_;
srcIgnore = srcIgnore_;
dstIgnore = dstIgnore_;
myGameTime = blockingMap->type.gameTime; myGameTime = blockingMap->type.gameTime;
nodes.clear(); nodes.clear();
@ -164,6 +184,8 @@ struct PathfindContext
std::vector<PathNode> nodes; ///< Edge of explored region of the map. std::vector<PathNode> nodes; ///< Edge of explored region of the map.
std::vector<PathExploredTile> map; ///< Map, with paths leading back to tileS. std::vector<PathExploredTile> map; ///< Map, with paths leading back to tileS.
PathBlockingMap const *blockingMap; ///< Map of blocking tiles for the type of object which needs a path. PathBlockingMap const *blockingMap; ///< Map of blocking tiles for the type of object which needs a path.
PathNonblockingArea srcIgnore; ///< Area of structure at source which should be considered nonblocking.
PathNonblockingArea dstIgnore; ///< Area of structure at destination which should be considered nonblocking.
}; };
/// Last recently used list of contexts. /// Last recently used list of contexts.
@ -344,9 +366,9 @@ static PathCoord fpathAStarExplore(PathfindContext &context, PathCoord tileF)
return nearestCoord; return nearestCoord;
} }
static void fpathInitContext(PathfindContext &context, PathBlockingMap const *blockingMap, PathCoord tileS, PathCoord tileRealS, PathCoord tileF) static void fpathInitContext(PathfindContext &context, PathBlockingMap const *blockingMap, PathCoord tileS, PathCoord tileRealS, PathCoord tileF, PathNonblockingArea srcIgnore, PathNonblockingArea dstIgnore)
{ {
context.assign(blockingMap, tileS); context.assign(blockingMap, tileS, srcIgnore, dstIgnore);
// Add the start point to the open list // Add the start point to the open list
fpathNewNode(context, tileF, tileRealS, 0, tileRealS); fpathNewNode(context, tileF, tileRealS, 0, tileRealS);
@ -361,13 +383,15 @@ ASR_RETVAL fpathAStarRoute(MOVE_CONTROL *psMove, PATHJOB *psJob)
const PathCoord tileOrig(map_coord(psJob->origX), map_coord(psJob->origY)); const PathCoord tileOrig(map_coord(psJob->origX), map_coord(psJob->origY));
const PathCoord tileDest(map_coord(psJob->destX), map_coord(psJob->destY)); const PathCoord tileDest(map_coord(psJob->destX), map_coord(psJob->destY));
const PathNonblockingArea srcIgnore(psJob->srcStructure);
const PathNonblockingArea dstIgnore(psJob->dstStructure);
PathCoord endCoord; // Either nearest coord (mustReverse = true) or orig (mustReverse = false). PathCoord endCoord; // Either nearest coord (mustReverse = true) or orig (mustReverse = false).
std::list<PathfindContext>::iterator contextIterator = fpathContexts.begin(); std::list<PathfindContext>::iterator contextIterator = fpathContexts.begin();
for (contextIterator = fpathContexts.begin(); contextIterator != fpathContexts.end(); ++contextIterator) for (contextIterator = fpathContexts.begin(); contextIterator != fpathContexts.end(); ++contextIterator)
{ {
if (!contextIterator->matches(psJob->blockingMap, tileDest)) if (!contextIterator->matches(psJob->blockingMap, tileDest, srcIgnore, dstIgnore))
{ {
// This context is not for the same droid type and same destination. // This context is not for the same droid type and same destination.
continue; continue;
@ -410,7 +434,7 @@ ASR_RETVAL fpathAStarRoute(MOVE_CONTROL *psMove, PATHJOB *psJob)
// Init a new context, overwriting the oldest one if we are caching too many. // Init a new context, overwriting the oldest one if we are caching too many.
// We will be searching from orig to dest, since we don't know where the nearest reachable tile to dest is. // We will be searching from orig to dest, since we don't know where the nearest reachable tile to dest is.
fpathInitContext(*contextIterator, psJob->blockingMap, tileOrig, tileOrig, tileDest); fpathInitContext(*contextIterator, psJob->blockingMap, tileOrig, tileOrig, tileDest, srcIgnore, dstIgnore);
endCoord = fpathAStarExplore(*contextIterator, tileDest); endCoord = fpathAStarExplore(*contextIterator, tileDest);
contextIterator->nearestCoord = endCoord; contextIterator->nearestCoord = endCoord;
} }
@ -492,7 +516,7 @@ ASR_RETVAL fpathAStarRoute(MOVE_CONTROL *psMove, PATHJOB *psJob)
if (!context.isBlocked(tileOrig.x, tileOrig.y)) // If blocked, searching from tileDest to tileOrig wouldn't find the tileOrig tile. if (!context.isBlocked(tileOrig.x, tileOrig.y)) // If blocked, searching from tileDest to tileOrig wouldn't find the tileOrig tile.
{ {
// Next time, search starting from nearest reachable tile to the destination. // Next time, search starting from nearest reachable tile to the destination.
fpathInitContext(context, psJob->blockingMap, tileDest, context.nearestCoord, tileOrig); fpathInitContext(context, psJob->blockingMap, tileDest, context.nearestCoord, tileOrig, srcIgnore, dstIgnore);
} }
} }
else else

View File

@ -27,6 +27,7 @@
#include "projectile.h" #include "projectile.h"
#include "structure.h" #include "structure.h"
#include "feature.h" #include "feature.h"
#include "intdisplay.h"
static inline uint16_t interpolateAngle(uint16_t v1, uint16_t v2, uint32_t t1, uint32_t t2, uint32_t t) static inline uint16_t interpolateAngle(uint16_t v1, uint16_t v2, uint32_t t1, uint32_t t2, uint32_t t)
@ -153,3 +154,16 @@ void _syncDebugObject(const char *function, SIMPLE_OBJECT const *psObject, char
break; break;
} }
} }
Vector2i getStatsSize(BASE_STATS const *pType, uint16_t direction)
{
if (StatIsStructure(pType))
{
return getStructureStatsSize(static_cast<STRUCTURE_STATS const *>(pType), direction);
}
else if(StatIsFeature(pType))
{
return getFeatureStatsSize(static_cast<FEATURE_STATS const *>(pType));
}
return Vector2i(1, 1);
}

View File

@ -41,4 +41,6 @@ void checkObject(const SIMPLE_OBJECT *psObject, const char *const location_descr
#define syncDebugObject(psObject, ch) _syncDebugObject(__FUNCTION__, psObject, ch) #define syncDebugObject(psObject, ch) _syncDebugObject(__FUNCTION__, psObject, ch)
void _syncDebugObject(const char *function, SIMPLE_OBJECT const *psObject, char ch); void _syncDebugObject(const char *function, SIMPLE_OBJECT const *psObject, char ch);
Vector2i getStatsSize(BASE_STATS const *pType, uint16_t direction);
#endif // __INCLUDED_BASEOBJECT_H__ #endif // __INCLUDED_BASEOBJECT_H__

View File

@ -1513,6 +1513,7 @@ void FinishDeliveryPosition(UDWORD xPos,UDWORD yPos,void *UserData)
//deselect it //deselect it
((FLAG_POSITION*)UserData)->selected = false; ((FLAG_POSITION*)UserData)->selected = false;
deliveryPointToMove = NULL;
CancelDeliveryRepos(); CancelDeliveryRepos();
} }
@ -3103,6 +3104,7 @@ void clearSel(void)
{ {
psFlagPos->selected = false; psFlagPos->selected = false;
} }
deliveryPointToMove = NULL;
setSelectedGroup(UBYTE_MAX); setSelectedGroup(UBYTE_MAX);
setSelectedCommander(UBYTE_MAX); setSelectedCommander(UBYTE_MAX);

View File

@ -1600,6 +1600,7 @@ void displayBlueprints(void)
} }
else else
{ {
ASSERT(deliveryPointToMove != NULL, "Expected a delivery point.");
if (deliveryPointToMove) if (deliveryPointToMove)
{ {
// it's a droid (from the debug menu) or a delivery point // it's a droid (from the debug menu) or a delivery point
@ -1609,18 +1610,6 @@ void displayBlueprints(void)
pos.coords.z = map_Height(pos.coords.x, pos.coords.y) + world_coord(1)/8; pos.coords.z = map_Height(pos.coords.x, pos.coords.y) + world_coord(1)/8;
renderDeliveryPoint(&pos, true); renderDeliveryPoint(&pos, true);
} }
else
{
// it's a droid (from the debug menu)
// no delivery point is known, so show a fake one
FLAG_POSITION pos;
pos.coords.x = world_coord(sBuildDetails.x)+world_coord(1)/2;
pos.coords.y = world_coord(sBuildDetails.y)+world_coord(1)/2;
pos.coords.z = map_Height(pos.coords.x, pos.coords.y) + world_coord(1)/8;
pos.factoryType = REPAIR_FLAG;
pos.factoryInc = 0;
renderDeliveryPoint(&pos, true);
}
} }
} }

View File

@ -416,9 +416,11 @@ void removeDroidBase(DROID *psDel)
return; return;
} }
syncDebugDroid(psDel, '#');
//ajl, inform others of destruction. //ajl, inform others of destruction.
// Everyone else should be doing this at the same time, assuming it's in synch (so everyone sends a GAME_DROIDDEST message at once)... // Everyone else should be doing this at the same time, assuming it's in synch (so everyone sends a GAME_DROIDDEST message at once)...
if (bMultiMessages if (!isInSync() && bMultiMessages
&& !(psDel->player != selectedPlayer && psDel->order == DORDER_RECYCLE)) && !(psDel->player != selectedPlayer && psDel->order == DORDER_RECYCLE))
{ {
ASSERT_OR_RETURN( , droidOnMap(psDel), "Asking other players to destroy droid driving off the map"); ASSERT_OR_RETURN( , droidOnMap(psDel), "Asking other players to destroy droid driving off the map");
@ -634,8 +636,9 @@ static void droidFlameFallCallback( ANIM_OBJECT * psObj )
ASSERT_OR_RETURN( , psDroid != NULL, "invalid Unit pointer"); ASSERT_OR_RETURN( , psDroid != NULL, "invalid Unit pointer");
psDroid->psCurAnim = NULL; psDroid->psCurAnim = NULL;
debug(LOG_DEATH, "droidFlameFallCallback: Droid %d destroyed", (int)psDroid->id); // This breaks synch, obviously. Animations are not synched, so changing game state as part of an animation is not completely ideal.
destroyDroid( psDroid ); //debug(LOG_DEATH, "droidFlameFallCallback: Droid %d destroyed", (int)psDroid->id);
//destroyDroid( psDroid );
} }
static void droidBurntCallback( ANIM_OBJECT * psObj ) static void droidBurntCallback( ANIM_OBJECT * psObj )
@ -668,6 +671,12 @@ void droidBurn(DROID *psDroid)
return; return;
} }
if (psDroid->order != DORDER_RUNBURN)
{
/* set droid running */
orderDroid(psDroid, DORDER_RUNBURN, ModeImmediate);
}
/* if already burning return else remove currently-attached anim if present */ /* if already burning return else remove currently-attached anim if present */
if ( psDroid->psCurAnim != NULL ) if ( psDroid->psCurAnim != NULL )
{ {
@ -700,9 +709,6 @@ void droidBurn(DROID *psDroid)
debug( LOG_NEVER, "baba burn" ); debug( LOG_NEVER, "baba burn" );
// NOTE: 3 types of screams are available ID_SOUND_BARB_SCREAM - ID_SOUND_BARB_SCREAM3 // NOTE: 3 types of screams are available ID_SOUND_BARB_SCREAM - ID_SOUND_BARB_SCREAM3
audio_PlayObjDynamicTrack( psDroid, ID_SOUND_BARB_SCREAM+(rand()%3), NULL ); audio_PlayObjDynamicTrack( psDroid, ID_SOUND_BARB_SCREAM+(rand()%3), NULL );
/* set droid running */
orderDroid(psDroid, DORDER_RUNBURN, ModeImmediate);
} }
void _syncDebugDroid(const char *function, DROID const *psDroid, char ch) void _syncDebugDroid(const char *function, DROID const *psDroid, char ch)
@ -2806,7 +2812,7 @@ bool calcDroidMuzzleLocation(DROID *psDroid, Vector3i *muzzle, int weapon_slot)
*muzzle = swapYZ(af*barrel); *muzzle = swapYZ(af*barrel);
muzzle->z = -muzzle->z; muzzle->z = -muzzle->z;
debugLen += sprintf(debugStr + debugLen, ",muzzle=(%d,%d,%d)", muzzle->x, muzzle->y, muzzle->z); sprintf(debugStr + debugLen, ",muzzle=(%d,%d,%d)", muzzle->x, muzzle->y, muzzle->z);
syncDebug("%s", debugStr); syncDebug("%s", debugStr);
} }
@ -3154,47 +3160,18 @@ static bool oneDroidMax(UDWORD x, UDWORD y)
// returns true if it's a sensible place to put that droid. // returns true if it's a sensible place to put that droid.
static bool sensiblePlace(SDWORD x, SDWORD y, PROPULSION_TYPE propulsion) static bool sensiblePlace(SDWORD x, SDWORD y, PROPULSION_TYPE propulsion)
{ {
UDWORD count=0;
// not too near the edges. // not too near the edges.
if((x < TOO_NEAR_EDGE) || (x > (SDWORD)(mapWidth - TOO_NEAR_EDGE))) if((x < TOO_NEAR_EDGE) || (x > (SDWORD)(mapWidth - TOO_NEAR_EDGE)))
return false; return false;
if((y < TOO_NEAR_EDGE) || (y > (SDWORD)(mapHeight - TOO_NEAR_EDGE))) if((y < TOO_NEAR_EDGE) || (y > (SDWORD)(mapHeight - TOO_NEAR_EDGE)))
return false; return false;
// check no features there
if(TileHasFeature(mapTile(x,y)))
{
return false;
}
// not on a blocking tile. // not on a blocking tile.
if (fpathBlockingTile(x, y, propulsion)) if (fpathBlockingTile(x, y, propulsion))
{ {
return false; return false;
} }
// shouldn't next to more than one blocking tile, to avoid windy paths.
if (fpathBlockingTile(x - 1, y - 1, propulsion))
count++;
if (fpathBlockingTile(x, y - 1, propulsion))
count++;
if (fpathBlockingTile(x + 1, y - 1, propulsion))
count++;
if (fpathBlockingTile(x - 1, y, propulsion))
count++;
if (fpathBlockingTile(x + 1, y, propulsion))
count++;
if (fpathBlockingTile(x -1, y + 1, propulsion))
count++;
if (fpathBlockingTile(x, y + 1, propulsion))
count++;
if (fpathBlockingTile(x +1, y + 1, propulsion))
count++;
if(count > 1)
return false;
return true; return true;
} }
@ -3278,12 +3255,6 @@ bool pickATileGenThreat(UDWORD *x, UDWORD *y, UBYTE numIterations, SDWORD threat
} }
/// find an empty tile accessible to a wheeled droid
bool pickATile(UDWORD *x, UDWORD *y, UBYTE numIterations)
{
return pickATileGen(x, y, numIterations, zonedPAT);
}
/// find a tile for a wheeled droid with only one other droid present /// find a tile for a wheeled droid with only one other droid present
PICKTILE pickHalfATile(UDWORD *x, UDWORD *y, UBYTE numIterations) PICKTILE pickHalfATile(UDWORD *x, UDWORD *y, UBYTE numIterations)
{ {

View File

@ -48,7 +48,7 @@
extern DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS]; extern DROID_TEMPLATE *apsDroidTemplates[MAX_PLAYERS];
extern DROID_TEMPLATE *apsStaticTemplates; // for AIs and scripts extern DROID_TEMPLATE *apsStaticTemplates; // for AIs and scripts
//used to stop structures being built too near the edge and droids being placed down - pickATile //used to stop structures being built too near the edge and droids being placed down
#define TOO_NEAR_EDGE 3 #define TOO_NEAR_EDGE 3
/* Define max number of allowed droids per droid type */ /* Define max number of allowed droids per droid type */
@ -70,7 +70,6 @@ enum PICKTILE
{ {
NO_FREE_TILE, NO_FREE_TILE,
FREE_TILE, FREE_TILE,
HALF_FREE_TILE
}; };
// the structure that was last hit // the structure that was last hit
@ -248,9 +247,7 @@ extern void droidSetName(DROID *psDroid, const char *pName);
// returns true when no droid on x,y square. // returns true when no droid on x,y square.
extern bool noDroid (UDWORD x, UDWORD y); // true if no droid at x,y extern bool noDroid (UDWORD x, UDWORD y); // true if no droid at x,y
// returns an x/y coord to place a droid // returns an x/y coord to place a droid
extern bool pickATile (UDWORD *x0,UDWORD *y0, UBYTE numIterations);
extern PICKTILE pickHalfATile (UDWORD *x, UDWORD *y, UBYTE numIterations); extern PICKTILE pickHalfATile (UDWORD *x, UDWORD *y, UBYTE numIterations);
extern bool pickATile2 (UDWORD *x, UDWORD *y, UDWORD numIterations);
extern bool zonedPAT(UDWORD x, UDWORD y); extern bool zonedPAT(UDWORD x, UDWORD y);
extern bool pickATileGen(UDWORD *x, UDWORD *y, UBYTE numIterations, extern bool pickATileGen(UDWORD *x, UDWORD *y, UBYTE numIterations,
bool (*function)(UDWORD x, UDWORD y)); bool (*function)(UDWORD x, UDWORD y));

View File

@ -1894,8 +1894,6 @@ static void renderSmokeEffect(const EFFECT *psEffect)
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
void effectSetupFirework(EFFECT *psEffect) void effectSetupFirework(EFFECT *psEffect)
{ {
UDWORD camExtra;
if(psEffect->type == FIREWORK_TYPE_LAUNCHER) if(psEffect->type == FIREWORK_TYPE_LAUNCHER)
{ {
psEffect->velocity.x = 200 - rand()%400; psEffect->velocity.x = 200 - rand()%400;
@ -1903,11 +1901,6 @@ void effectSetupFirework(EFFECT *psEffect)
psEffect->velocity.y = 400 + rand()%200; //height psEffect->velocity.y = 400 + rand()%200; //height
psEffect->lifeSpan = GAME_TICKS_PER_SEC * 3; psEffect->lifeSpan = GAME_TICKS_PER_SEC * 3;
psEffect->radius = 80 + rand()%150; psEffect->radius = 80 + rand()%150;
camExtra = 0;
if(getCampaignNumber()!=1)
{
camExtra+=rand()%200;
}
psEffect->size = 300+rand()%300; //height it goes off psEffect->size = 300+rand()%300; //height it goes off
psEffect->imd = getImdFromIndex(MI_FIREWORK); // not actually drawn psEffect->imd = getImdFromIndex(MI_FIREWORK); // not actually drawn
} }
@ -1939,9 +1932,7 @@ void effectSetupFirework(EFFECT *psEffect)
break; break;
} }
} }
psEffect->frameDelay = (EXPLOSION_FRAME_DELAY*2); psEffect->frameDelay = (EXPLOSION_FRAME_DELAY*2);
} }
void effectSetupSmoke(EFFECT *psEffect) void effectSetupSmoke(EFFECT *psEffect)

View File

@ -260,6 +260,7 @@ FEATURE * buildFeature(FEATURE_STATS *psStats, UDWORD x, UDWORD y,bool FromSave)
psFeature->rot.direction = 0; psFeature->rot.direction = 0;
} }
psFeature->body = psStats->body; psFeature->body = psStats->body;
psFeature->inFire = false;
objSensorCache((BASE_OBJECT *)psFeature, NULL); objSensorCache((BASE_OBJECT *)psFeature, NULL);
objEcmCache((BASE_OBJECT *)psFeature, NULL); objEcmCache((BASE_OBJECT *)psFeature, NULL);
@ -556,3 +557,11 @@ SDWORD getFeatureStatFromName( const char *pName )
} }
return -1; return -1;
} }
Vector2i getFeatureStatsSize(FEATURE_STATS const *pFeatureType)
{
Vector2i size(pFeatureType->baseWidth, pFeatureType->baseBreadth);
// Feature has normal orientation (or upsidedown).
return size;
}

View File

@ -58,6 +58,8 @@ int32_t featureDamage(FEATURE *psFeature, UDWORD damage, WEAPON_CLASS weaponClas
extern void featureInitVars(void); extern void featureInitVars(void);
Vector2i getFeatureStatsSize(FEATURE_STATS const *pStructureType);
#define syncDebugFeature(psFeature, ch) _syncDebugFeature(__FUNCTION__, psFeature, ch) #define syncDebugFeature(psFeature, ch) _syncDebugFeature(__FUNCTION__, psFeature, ch)
void _syncDebugFeature(const char *function, FEATURE const *psFeature, char ch); void _syncDebugFeature(const char *function, FEATURE const *psFeature, char ch);

View File

@ -350,9 +350,31 @@ void fpathRemoveDroidData(int id)
wzMutexUnlock(fpathMutex); wzMutexUnlock(fpathMutex);
} }
static StructureTiles getTilesOfStructure(BASE_OBJECT *object)
{
StructureTiles ret;
ret.size = Vector2i(-65535, -65535); // Default to an invalid area.
ret.map = Vector2i(32767, 32767);
STRUCTURE *psStructure = castStructure(object);
FEATURE *psFeature = castFeature(object);
if (psStructure != NULL)
{
ret.size = getStructureSize(psStructure);
ret.map = map_coord(removeZ(psStructure->pos)) - ret.size/2;
}
else if (psFeature != NULL)
{
ret.size = Vector2i(psFeature->psStats->baseWidth, psFeature->psStats->baseBreadth);
ret.map = map_coord(removeZ(psFeature->pos)) - ret.size/2;
}
return ret;
}
static FPATH_RETVAL fpathRoute(MOVE_CONTROL *psMove, int id, int startX, int startY, int tX, int tY, PROPULSION_TYPE propulsionType, static FPATH_RETVAL fpathRoute(MOVE_CONTROL *psMove, int id, int startX, int startY, int tX, int tY, PROPULSION_TYPE propulsionType,
DROID_TYPE droidType, FPATH_MOVETYPE moveType, int owner, bool acceptNearest) DROID_TYPE droidType, FPATH_MOVETYPE moveType, int owner, bool acceptNearest, BASE_OBJECT *srcStructure, BASE_OBJECT *dstStructure)
{ {
objTrace(id, "called(*,id=%d,sx=%d,sy=%d,ex=%d,ey=%d,prop=%d,type=%d,move=%d,owner=%d)", id, startX, startY, tX, tY, (int)propulsionType, (int)droidType, (int)moveType, owner); objTrace(id, "called(*,id=%d,sx=%d,sy=%d,ex=%d,ey=%d,prop=%d,type=%d,move=%d,owner=%d)", id, startX, startY, tX, tY, (int)propulsionType, (int)droidType, (int)moveType, owner);
@ -424,6 +446,8 @@ static FPATH_RETVAL fpathRoute(MOVE_CONTROL *psMove, int id, int startX, int sta
job.droidID = id; job.droidID = id;
job.destX = tX; job.destX = tX;
job.destY = tY; job.destY = tY;
job.srcStructure = getTilesOfStructure(srcStructure);
job.dstStructure = getTilesOfStructure(dstStructure);
job.droidType = droidType; job.droidType = droidType;
job.propulsion = propulsionType; job.propulsion = propulsionType;
job.moveType = moveType; job.moveType = moveType;
@ -472,10 +496,18 @@ FPATH_RETVAL fpathDroidRoute(DROID* psDroid, SDWORD tX, SDWORD tY, FPATH_MOVETYP
// Check whether the start and end points of the route are blocking tiles and find an alternative if they are. // Check whether the start and end points of the route are blocking tiles and find an alternative if they are.
Position startPos = psDroid->pos; Position startPos = psDroid->pos;
Position endPos = Position(tX, tY, 0); Position endPos = Position(tX, tY, 0);
BASE_OBJECT *srcStructure = worldTile(startPos)->psObject;
BASE_OBJECT *dstStructure = worldTile(endPos)->psObject;
if (psDroid->sMove.Status != MOVEWAITROUTE) if (psDroid->sMove.Status != MOVEWAITROUTE)
{ {
startPos = findNonblockingPosition(startPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType); if (srcStructure == NULL) // If there's a structure over the source, ignore it, otherwise pathfind from somewhere around the obstruction.
endPos = findNonblockingPosition(endPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType); {
startPos = findNonblockingPosition(startPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType);
}
if (dstStructure == NULL) // If there's a structure over the destination, ignore it, otherwise pathfind from somewhere around the obstruction.
{
endPos = findNonblockingPosition(endPos, getPropulsionStats(psDroid)->propulsionType, psDroid->player, moveType);
}
objTrace(psDroid->id, "Want to go to (%d, %d) -> (%d, %d), going (%d, %d) -> (%d, %d)", map_coord(psDroid->pos.x), map_coord(psDroid->pos.y), map_coord(tX), map_coord(tY), map_coord(startPos.x), map_coord(startPos.y), map_coord(endPos.x), map_coord(endPos.y)); objTrace(psDroid->id, "Want to go to (%d, %d) -> (%d, %d), going (%d, %d) -> (%d, %d)", map_coord(psDroid->pos.x), map_coord(psDroid->pos.y), map_coord(tX), map_coord(tY), map_coord(startPos.x), map_coord(startPos.y), map_coord(endPos.x), map_coord(endPos.y));
} }
switch (psDroid->order) switch (psDroid->order)
@ -492,7 +524,7 @@ FPATH_RETVAL fpathDroidRoute(DROID* psDroid, SDWORD tX, SDWORD tY, FPATH_MOVETYP
break; break;
} }
return fpathRoute(&psDroid->sMove, psDroid->id, startPos.x, startPos.y, endPos.x, endPos.y, psPropStats->propulsionType, return fpathRoute(&psDroid->sMove, psDroid->id, startPos.x, startPos.y, endPos.x, endPos.y, psPropStats->propulsionType,
psDroid->droidType, moveType, psDroid->player, acceptNearest); psDroid->droidType, moveType, psDroid->player, acceptNearest, srcStructure, dstStructure);
} }
// Run only from path thread // Run only from path thread
@ -595,7 +627,7 @@ static int fpathResultQueueLength(void)
// Only used by fpathTest. // Only used by fpathTest.
static FPATH_RETVAL fpathSimpleRoute(MOVE_CONTROL *psMove, int id, int startX, int startY, int tX, int tY) static FPATH_RETVAL fpathSimpleRoute(MOVE_CONTROL *psMove, int id, int startX, int startY, int tX, int tY)
{ {
return fpathRoute(psMove, id, startX, startY, tX, tY, PROPULSION_TYPE_WHEELED, DROID_WEAPON, FMT_BLOCK, 0, true); return fpathRoute(psMove, id, startX, startY, tX, tY, PROPULSION_TYPE_WHEELED, DROID_WEAPON, FMT_BLOCK, 0, true, NULL, NULL);
} }
void fpathTest(int x, int y, int x2, int y2) void fpathTest(int x, int y, int x2, int y2)

View File

@ -41,12 +41,20 @@ enum FPATH_MOVETYPE
struct PathBlockingMap; struct PathBlockingMap;
struct StructureTiles
{
Vector2i map; ///< Map coordinates of upper left corner of structure.
Vector2i size; ///< Size (in map coordinates) of the structure.
};
struct PATHJOB struct PATHJOB
{ {
PROPULSION_TYPE propulsion; PROPULSION_TYPE propulsion;
DROID_TYPE droidType; DROID_TYPE droidType;
int destX, destY; int destX, destY;
int origX, origY; int origX, origY;
StructureTiles srcStructure;
StructureTiles dstStructure;
UDWORD droidID; UDWORD droidID;
FPATH_MOVETYPE moveType; FPATH_MOVETYPE moveType;
int owner; ///< Player owner int owner; ///< Player owner

View File

@ -4790,7 +4790,6 @@ static bool loadSaveStructure2(const char *pFileName, STRUCTURE **ppList)
} }
//clear subject //clear subject
psResearch->psSubject = NULL; psResearch->psSubject = NULL;
psResearch->timeStarted = 0;
psResearch->timeStartHold = 0; psResearch->timeStartHold = 0;
//set the subject //set the subject
if (ini.contains("Research/target")) if (ini.contains("Research/target"))
@ -4799,7 +4798,6 @@ static bool loadSaveStructure2(const char *pFileName, STRUCTURE **ppList)
if (researchId != NULL_ID) if (researchId != NULL_ID)
{ {
psResearch->psSubject = &asResearch[researchId]; psResearch->psSubject = &asResearch[researchId];
psResearch->timeStarted = ini.value("Research/timeStarted").toInt();
psResearch->timeStartHold = ini.value("Research/timeStartHold").toInt(); psResearch->timeStartHold = ini.value("Research/timeStartHold").toInt();
} }
else else
@ -4821,8 +4819,6 @@ static bool loadSaveStructure2(const char *pFileName, STRUCTURE **ppList)
case REF_REPAIR_FACILITY: case REF_REPAIR_FACILITY:
psRepair = ((REPAIR_FACILITY *)psStructure->pFunctionality); psRepair = ((REPAIR_FACILITY *)psStructure->pFunctionality);
psRepair->power = ((REPAIR_DROID_FUNCTION *) psStructure->pStructureType->asFuncList[0])->repairPoints; psRepair->power = ((REPAIR_DROID_FUNCTION *) psStructure->pStructureType->asFuncList[0])->repairPoints;
psRepair->timeStarted = ini.value("Repair/timeStarted").toInt();
psRepair->currentPtsAdded = ini.value("Repair/currentPtsAdded").toInt();
if (ini.contains("Repair/deliveryPoint/pos")) if (ini.contains("Repair/deliveryPoint/pos"))
{ {
Position point = ini.vector3i("Repair/deliveryPoint/pos"); Position point = ini.vector3i("Repair/deliveryPoint/pos");
@ -5000,7 +4996,6 @@ bool writeStructFile(const char *pFileName)
if (((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject) if (((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject)
{ {
ini.setValue("Research/target", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject->pName); ini.setValue("Research/target", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->psSubject->pName);
ini.setValue("Research/timeStarted", ((RESEARCH_FACILITY *)psCurr->pFunctionality)->timeStarted);
} }
} }
else if (psCurr->pStructureType->type == REF_POWER_GEN) else if (psCurr->pStructureType->type == REF_POWER_GEN)
@ -5010,8 +5005,6 @@ bool writeStructFile(const char *pFileName)
else if (psCurr->pStructureType->type == REF_REPAIR_FACILITY) else if (psCurr->pStructureType->type == REF_REPAIR_FACILITY)
{ {
REPAIR_FACILITY *psRepair = ((REPAIR_FACILITY *)psCurr->pFunctionality); REPAIR_FACILITY *psRepair = ((REPAIR_FACILITY *)psCurr->pFunctionality);
ini.setValue("Repair/timeStarted", psRepair->timeStarted);
ini.setValue("Repair/currentPtsAdded", psRepair->currentPtsAdded);
if (psRepair->psObj) if (psRepair->psObj)
{ {
ini.setValue("Repair/target/id", psRepair->psObj->id); ini.setValue("Repair/target/id", psRepair->psObj->id);

View File

@ -96,23 +96,11 @@ bool gwNewGateway(SDWORD x1, SDWORD y1, SDWORD x2, SDWORD y2)
GATEWAY *psNew; GATEWAY *psNew;
SDWORD pos, temp; SDWORD pos, temp;
if ((x1 < 0) || (x1 >= gwMapWidth()) || ASSERT_OR_RETURN(false, x1 >= 0 && x1 < gwMapWidth() && y1 >= 0 && y1 < gwMapHeight()
(y1 < 0) || (y1 >= gwMapHeight()) || && x2 >= 0 && x2 < gwMapWidth() && y2 >= 0 && y2 < gwMapHeight()
(x2 < 0) || (x2 >= gwMapWidth()) || && (x1 == x2 || y1 == y2), "Invalid gateway coordinates (%d, %d, %d, %d)",
(y2 < 0) || (y2 >= gwMapHeight()) || x1, y1, x2, y2);
((x1 != x2) && (y1 != y2)))
{
ASSERT( false,"gwNewGateway: invalid coordinates" );
return false;
}
psNew = (GATEWAY*)malloc(sizeof(GATEWAY)); psNew = (GATEWAY*)malloc(sizeof(GATEWAY));
if (!psNew)
{
debug( LOG_FATAL, "gwNewGateway: out of memory" );
abort();
return false;
}
// make sure the first coordinate is always the smallest // make sure the first coordinate is always the smallest
if (x2 < x1) if (x2 < x1)

View File

@ -64,6 +64,7 @@ DROID_GROUP::DROID_GROUP()
refCount = 0; refCount = 0;
psList = NULL; psList = NULL;
psCommander = NULL; psCommander = NULL;
memset(&sRunData, 0, sizeof(sRunData));
} }
// create a new group // create a new group

View File

@ -85,6 +85,8 @@
static UDWORD newMapWidth, newMapHeight; static UDWORD newMapWidth, newMapHeight;
static FLAG_POSITION debugMenuDroidDeliveryPoint;
#define RETXOFFSET (0)// Reticule button offset #define RETXOFFSET (0)// Reticule button offset
#define RETYOFFSET (0) #define RETYOFFSET (0)
#define NUMRETBUTS 7 // Number of reticule buttons. #define NUMRETBUTS 7 // Number of reticule buttons.
@ -1351,27 +1353,13 @@ static void intProcessEditStats(UDWORD id)
{ {
/* Clicked on a stat button - need to look for a location for it */ /* Clicked on a stat button - need to look for a location for it */
psPositionStats = ppsStatsList[id - IDSTAT_START]; psPositionStats = ppsStatsList[id - IDSTAT_START];
/*if it is a structure - need to check there is enough power available
to build */
if (psPositionStats->ref >= REF_STRUCTURE_START &&
psPositionStats->ref < REF_STRUCTURE_START + REF_RANGE)
{
if (!checkPower(selectedPlayer, ((STRUCTURE_STATS*)psPositionStats)->powerToBuild))
{
debug(LOG_INFO, "Ignoring power check, this is only used from the edit menu, isn't it?");
//return;
}
}
/*if it is a template - need to check there is enough power available
to build */
if (psPositionStats->ref >= REF_TEMPLATE_START && if (psPositionStats->ref >= REF_TEMPLATE_START &&
psPositionStats->ref < REF_TEMPLATE_START + REF_RANGE) psPositionStats->ref < REF_TEMPLATE_START + REF_RANGE)
{ {
if (!checkPower(selectedPlayer, ((DROID_TEMPLATE*)psPositionStats)->powerPoints)) // Placing a droid from the debug menu, set up the flag. (This would probably be safe to do, even if we're placing something else.)
{ debugMenuDroidDeliveryPoint.factoryType = REPAIR_FLAG;
debug(LOG_INFO, "Ignoring power check, this is only used from the edit menu, isn't it?"); debugMenuDroidDeliveryPoint.factoryInc = 0;
return; deliveryPointToMove = &debugMenuDroidDeliveryPoint;
}
} }
intStartStructPosition(psPositionStats); intStartStructPosition(psPositionStats);
editPosMode = IED_POS; editPosMode = IED_POS;
@ -2052,7 +2040,6 @@ INT_RETVAL intRunWidgets(void)
debug( LOG_ERROR, "PlayerHasLost Or Won\n" ); debug( LOG_ERROR, "PlayerHasLost Or Won\n" );
intResetScreen(true); intResetScreen(true);
retCode = INT_QUIT; retCode = INT_QUIT;
quitting = true;
} }
return retCode; return retCode;
} }
@ -2974,11 +2961,10 @@ void intNewObj(BASE_OBJECT *psObj)
// clean up when an object dies // clean up when an object dies
static void intObjectDied(UDWORD objID) static void intObjectDied(UDWORD objID)
{ {
RENDERED_BUTTON *psBut;
UDWORD statsID, gubbinsID; UDWORD statsID, gubbinsID;
// clear the object button // clear the object button
psBut = (RENDERED_BUTTON *)widgGetUserData(psWScreen, objID); RENDERED_BUTTON *psBut = (RENDERED_BUTTON *)widgGetUserData(psWScreen, objID);
if (psBut) if (psBut)
{ {
psBut->Data = NULL; psBut->Data = NULL;
@ -2993,7 +2979,6 @@ static void intObjectDied(UDWORD objID)
// clear the stats button // clear the stats button
statsID = IDOBJ_STATSTART + objID - IDOBJ_OBJSTART; statsID = IDOBJ_STATSTART + objID - IDOBJ_OBJSTART;
intSetStats(statsID, NULL); intSetStats(statsID, NULL);
psBut = (RENDERED_BUTTON *)widgGetUserData(psWScreen, statsID);
// and disable it // and disable it
widgSetButtonState(psWScreen, statsID, WBUT_DISABLE); widgSetButtonState(psWScreen, statsID, WBUT_DISABLE);
@ -3754,13 +3739,11 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected,b
DROID *Droid; DROID *Droid;
STRUCTURE *Structure; STRUCTURE *Structure;
bool IsFactory; bool IsFactory;
bool Animate = true;
int compIndex; int compIndex;
// Is the form already up? // Is the form already up?
if(widgGetFromID(psWScreen,IDOBJ_FORM) != NULL) { if(widgGetFromID(psWScreen,IDOBJ_FORM) != NULL) {
intRemoveObjectNoAnim(); intRemoveObjectNoAnim();
Animate = false;
} }
else else
{ {
@ -3768,8 +3751,6 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected,b
asJumpPos.clear(); asJumpPos.clear();
} }
Animate = false;
ClearObjectBuffers(); ClearObjectBuffers();
ClearTopicBuffers(); ClearTopicBuffers();
@ -3877,14 +3858,7 @@ static bool intAddObjectWindow(BASE_OBJECT *psObjects, BASE_OBJECT *psSelected,b
sFormInit.y = (SWORD)OBJ_BACKY; sFormInit.y = (SWORD)OBJ_BACKY;
sFormInit.width = OBJ_BACKWIDTH; sFormInit.width = OBJ_BACKWIDTH;
sFormInit.height = OBJ_BACKHEIGHT; sFormInit.height = OBJ_BACKHEIGHT;
// If the window was closed then do open animation. sFormInit.pDisplay = intDisplayPlainForm;
if(Animate) {
sFormInit.pDisplay = intOpenPlainForm;
sFormInit.disableChildren = true;
} else {
// otherwise just recreate it.
sFormInit.pDisplay = intDisplayPlainForm;
}
if (!widgAddForm(psWScreen, &sFormInit)) if (!widgAddForm(psWScreen, &sFormInit))
{ {
return false; return false;
@ -4768,7 +4742,6 @@ static bool intAddStats(BASE_STATS **ppsStatsList, UDWORD numStats,
UDWORD i, butPerForm, statForm; UDWORD i, butPerForm, statForm;
SDWORD BufferID; SDWORD BufferID;
BASE_STATS *Stat; BASE_STATS *Stat;
bool Animate = true;
FACTORY *psFactory; FACTORY *psFactory;
int allyResearchIconCount = 0; int allyResearchIconCount = 0;
@ -4778,7 +4751,6 @@ static bool intAddStats(BASE_STATS **ppsStatsList, UDWORD numStats,
// Is the form already up? // Is the form already up?
if(widgGetFromID(psWScreen,IDSTAT_FORM) != NULL) { if(widgGetFromID(psWScreen,IDSTAT_FORM) != NULL) {
intRemoveStatsNoAnim(); intRemoveStatsNoAnim();
Animate = false;
} }
// is the order form already up ? // is the order form already up ?
@ -4787,8 +4759,6 @@ static bool intAddStats(BASE_STATS **ppsStatsList, UDWORD numStats,
intRemoveOrderNoAnim(); intRemoveOrderNoAnim();
} }
Animate = false;
if (psOwner != NULL) if (psOwner != NULL)
{ {
// Return if the owner is dead. // Return if the owner is dead.
@ -4815,14 +4785,7 @@ static bool intAddStats(BASE_STATS **ppsStatsList, UDWORD numStats,
sFormInit.y = (SWORD)STAT_Y; sFormInit.y = (SWORD)STAT_Y;
sFormInit.width = STAT_WIDTH; sFormInit.width = STAT_WIDTH;
sFormInit.height = STAT_HEIGHT; sFormInit.height = STAT_HEIGHT;
// If the window was closed then do open animation. sFormInit.pDisplay = intDisplayPlainForm;
if(Animate) {
sFormInit.pDisplay = intOpenPlainForm;
sFormInit.disableChildren = true;
} else {
// otherwise just recreate it.
sFormInit.pDisplay = intDisplayPlainForm;
}
if (!widgAddForm(psWScreen, &sFormInit)) if (!widgAddForm(psWScreen, &sFormInit))
{ {
debug(LOG_ERROR, "intAddStats: Failed to add form"); debug(LOG_ERROR, "intAddStats: Failed to add form");
@ -5475,7 +5438,6 @@ static bool setResearchStats(BASE_OBJECT *psObj, BASE_STATS *psStats)
sendResearchStatus(psBuilding,count,selectedPlayer,true); // inform others, I'm researching this. sendResearchStatus(psBuilding,count,selectedPlayer,true); // inform others, I'm researching this.
MakeResearchStarted(pPlayerRes); MakeResearchStarted(pPlayerRes);
psResFacilty->timeStarted = ACTION_START_TIME;
psResFacilty->timeStartHold = 0; psResFacilty->timeStartHold = 0;
//stop the button from flashing once a topic has been chosen //stop the button from flashing once a topic has been chosen
stopReticuleButtonFlash(IDRET_RESEARCH); stopReticuleButtonFlash(IDRET_RESEARCH);
@ -5846,12 +5808,9 @@ void stopReticuleButtonFlash(UDWORD buttonID)
{ {
UBYTE DownTime = UNPACKDWORD_QUAD_C(psButton->UserData); UBYTE DownTime = UNPACKDWORD_QUAD_C(psButton->UserData);
UBYTE Index = UNPACKDWORD_QUAD_D(psButton->UserData); UBYTE Index = UNPACKDWORD_QUAD_D(psButton->UserData);
UBYTE flashing = UNPACKDWORD_QUAD_A(psButton->UserData);
UBYTE flashTime = UNPACKDWORD_QUAD_B(psButton->UserData);
// clear flashing byte // clear flashing byte
flashing = false; UBYTE flashing = false;
flashTime = 0; UBYTE flashTime = 0;
psButton->UserData = PACKDWORD_QUAD(flashTime,flashing,DownTime,Index); psButton->UserData = PACKDWORD_QUAD(flashTime,flashing,DownTime,Index);
} }
} }
@ -6271,7 +6230,6 @@ STRUCTURE* intGotoNextStructureType(UDWORD structType,bool JumpTo,bool CancelDri
} }
psStruct->selected = true; psStruct->selected = true;
CurrentStruct = psStruct; CurrentStruct = psStruct;
Found = true;
break; break;
} }
} }

View File

@ -2712,13 +2712,13 @@ DROID_TEMPLATE *FactoryGetTemplate(FACTORY *Factory)
return (DROID_TEMPLATE *)Factory->psSubject; return (DROID_TEMPLATE *)Factory->psSubject;
} }
bool StatIsStructure(BASE_STATS *Stat) bool StatIsStructure(BASE_STATS const *Stat)
{ {
return (Stat->ref >= REF_STRUCTURE_START && Stat->ref < return (Stat->ref >= REF_STRUCTURE_START && Stat->ref <
REF_STRUCTURE_START + REF_RANGE); REF_STRUCTURE_START + REF_RANGE);
} }
bool StatIsFeature(BASE_STATS *Stat) bool StatIsFeature(BASE_STATS const *Stat)
{ {
return (Stat->ref >= REF_FEATURE_START && Stat->ref < return (Stat->ref >= REF_FEATURE_START && Stat->ref <
REF_FEATURE_START + REF_RANGE); REF_FEATURE_START + REF_RANGE);

View File

@ -244,10 +244,10 @@ FACTORY *StructureGetFactory(STRUCTURE *Structure);
//SDWORD ResearchGetImage(RESEARCH_FACILITY *Research); //SDWORD ResearchGetImage(RESEARCH_FACILITY *Research);
bool StatIsStructure(BASE_STATS *Stat); bool StatIsStructure(BASE_STATS const *Stat);
iIMDShape *StatGetStructureIMD(BASE_STATS *Stat,UDWORD Player); iIMDShape *StatGetStructureIMD(BASE_STATS *Stat,UDWORD Player);
bool StatIsTemplate(BASE_STATS *Stat); bool StatIsTemplate(BASE_STATS *Stat);
bool StatIsFeature(BASE_STATS *Stat); bool StatIsFeature(BASE_STATS const *Stat);
SDWORD StatIsComponent(BASE_STATS *Stat); SDWORD StatIsComponent(BASE_STATS *Stat);
bool StatGetComponentIMD(BASE_STATS *Stat, SDWORD compID,iIMDShape **CompIMD,iIMDShape **MountIMD); bool StatGetComponentIMD(BASE_STATS *Stat, SDWORD compID,iIMDShape **CompIMD,iIMDShape **MountIMD);

View File

@ -1266,16 +1266,15 @@ void intDisplayPIEView(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DECL
MESSAGE *psMessage = (MESSAGE *)Form->pUserData; MESSAGE *psMessage = (MESSAGE *)Form->pUserData;
UDWORD x0,y0,x1,y1; UDWORD x0,y0,x1,y1;
SWORD image = -1; SWORD image = -1;
RESEARCH *psResearch; RESEARCH *psResearch;
// Should not have any proximity messages here...
//shouldn't have any proximity messages here... if (!psMessage || psMessage->type == MSG_PROXIMITY)
if (psMessage->type == MSG_PROXIMITY)
{ {
return; return;
} }
if (psMessage && psMessage->pViewData) if (psMessage->pViewData)
{ {
x0 = xOffset+Form->x; x0 = xOffset+Form->x;
y0 = yOffset+Form->y; y0 = yOffset+Form->y;
@ -1321,12 +1320,12 @@ void intDisplayFLICView(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DEC
VIEW_RESEARCH *psViewResearch; VIEW_RESEARCH *psViewResearch;
//shouldn't have any proximity messages here... //shouldn't have any proximity messages here...
if (psMessage->type == MSG_PROXIMITY) if (!psMessage || psMessage->type == MSG_PROXIMITY)
{ {
return; return;
} }
if (psMessage && psMessage->pViewData) if (psMessage->pViewData)
{ {
OpenButtonRender((UWORD)(xOffset+Form->x), (UWORD)(yOffset+Form->y), OpenButtonRender((UWORD)(xOffset+Form->x), (UWORD)(yOffset+Form->y),
Form->width, Form->height); Form->width, Form->height);
@ -1350,7 +1349,6 @@ void intDisplayFLICView(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DEC
seq_RenderVideoToBuffer(psViewResearch->sequenceName, SEQUENCE_HOLD); seq_RenderVideoToBuffer(psViewResearch->sequenceName, SEQUENCE_HOLD);
CloseButtonRender(); CloseButtonRender();
} }
} }
#endif #endif

View File

@ -1161,7 +1161,6 @@ static bool intRefreshOrderButtons(void)
{ {
SECONDARY_STATE State; SECONDARY_STATE State;
UWORD OrdIndex; UWORD OrdIndex;
UWORD NumButs;
UDWORD id; UDWORD id;
for (unsigned j = 0; j < AvailableOrders.size() && j < MAX_DISPLAYABLE_ORDERS; ++j) for (unsigned j = 0; j < AvailableOrders.size() && j < MAX_DISPLAYABLE_ORDERS; ++j)
@ -1171,25 +1170,8 @@ static bool intRefreshOrderButtons(void)
// Get current order state. // Get current order state.
State = GetSecondaryStates(OrderButtons[OrdIndex].Order); State = GetSecondaryStates(OrderButtons[OrdIndex].Order);
// Get number of buttons.
NumButs = OrderButtons[OrdIndex].NumButs;
// Set actual number of buttons. // Set actual number of buttons.
OrderButtons[OrdIndex].AcNumButs = NumButs; OrderButtons[OrdIndex].AcNumButs = OrderButtons[OrdIndex].NumButs;
// Handle special case for factory -> command droid assignment buttons.
switch (OrderButtons[OrdIndex].Class) {
case ORDBUTCLASS_FACTORY:
NumButs = countAssignableFactories((UBYTE)selectedPlayer,FACTORY_FLAG);
break;
case ORDBUTCLASS_CYBORGFACTORY:
NumButs = countAssignableFactories((UBYTE)selectedPlayer,CYBORG_FLAG);
break;
case ORDBUTCLASS_VTOLFACTORY:
NumButs = countAssignableFactories((UBYTE)selectedPlayer,VTOL_FLAG);
break;
default:
break;
}
id = OrderButtons[OrdIndex].ButBaseID; id = OrderButtons[OrdIndex].ButBaseID;
for (unsigned i = 0; i < OrderButtons[OrdIndex].AcNumButs; ++i) for (unsigned i = 0; i < OrderButtons[OrdIndex].AcNumButs; ++i)

View File

@ -2575,9 +2575,12 @@ float available_speed[] = {
5.f / 2.f, // n 5.f / 2.f, // n
3.f / 1.f, // n 3.f / 1.f, // n
10.f / 1.f, // n 10.f / 1.f, // n
20.f / 1.f // n 20.f / 1.f, // n
30.f / 1.f, // n
60.f / 1.f, // n
100.f / 1.f, // n
}; };
unsigned int nb_available_speeds = 12; unsigned int nb_available_speeds = ARRAY_SIZE(available_speed);
void kf_SpeedUp( void ) void kf_SpeedUp( void )
{ {
@ -2820,7 +2823,6 @@ void kf_BuildPrevPage()
temp = psTForm->majorT - 1; temp = psTForm->majorT - 1;
if (temp < 0) if (temp < 0)
{ {
temp = 0 ;
audio_PlayTrack(ID_SOUND_BUILD_FAIL); audio_PlayTrack(ID_SOUND_BUILD_FAIL);
return; return;
} }

View File

@ -136,52 +136,14 @@ SDWORD nextMissionType = LDS_NONE;//MISSION_NONE;
/* Force 3D display */ /* Force 3D display */
UDWORD mcTime; UDWORD mcTime;
/* The main game loop */ static GAMECODE renderLoop()
GAMECODE gameLoop(void)
{ {
DROID *psCurr, *psNext;
STRUCTURE *psCBuilding, *psNBuilding;
FEATURE *psCFeat, *psNFeat;
UDWORD i,widgval;
bool quitting=false;
INT_RETVAL intRetVal;
int clearMode = 0;
bool gameTicked; // true iff we are doing a logical update.
uint32_t lastFlushTime = 0;
// Receive NET_BLAH messages.
// Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime.
recvMessage();
// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
gameTimeUpdate();
gameTicked = deltaGameTime != 0;
if (gameTicked)
{
// Can't dump isHumanPlayer, since it causes spurious desynch dumps when players leave.
// TODO isHumanPlayer should probably be synchronised, since the game state seems to depend on it, so there might also be a risk of real desynchs when players leave.
//syncDebug("map = \"%s\", humanPlayers = %d %d %d %d %d %d %d %d", game.map, isHumanPlayer(0), isHumanPlayer(1), isHumanPlayer(2), isHumanPlayer(3), isHumanPlayer(4), isHumanPlayer(5), isHumanPlayer(6), isHumanPlayer(7));
syncDebug("map = \"%s\"", game.map);
// Actually send pending droid orders.
sendQueuedDroidInfo();
sendPlayerGameTime();
gameSRand(gameTime); // Brute force way of synchronising the random number generator, which can't go out of synch.
}
if (gameTicked || realTime - lastFlushTime < 400u)
{
lastFlushTime = realTime;
NETflush(); // Make sure the game time tick message is really sent over the network, and that we aren't waiting too long to send data.
}
if (bMultiPlayer && !NetPlay.isHostAlive && NetPlay.bComms && !NetPlay.isHost) if (bMultiPlayer && !NetPlay.isHostAlive && NetPlay.bComms && !NetPlay.isHost)
{ {
intAddInGamePopup(); intAddInGamePopup();
} }
int clearMode = 0;
if(getDrawShadows()) if(getDrawShadows())
{ {
clearMode |= CLEAR_SHADOW; clearMode |= CLEAR_SHADOW;
@ -199,31 +161,14 @@ GAMECODE gameLoop(void)
wzShowMouse(true); wzShowMouse(true);
INT_RETVAL intRetVal = INT_NONE;
if (!paused) if (!paused)
{ {
if (!scriptPaused() && !editPaused() && gameTicked)
{
/* Update the event system */
if (!bInTutorial)
{
eventProcessTriggers(gameTime/SCR_TICKRATE);
}
else
{
eventProcessTriggers(realTime/SCR_TICKRATE);
}
updateScripts();
}
/* Run the in game interface and see if it grabbed any mouse clicks */ /* Run the in game interface and see if it grabbed any mouse clicks */
if (!rotActive && getWidgetsStatus() && dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING) if (!rotActive && getWidgetsStatus() && dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING)
{ {
intRetVal = intRunWidgets(); intRetVal = intRunWidgets();
} }
else
{
intRetVal = INT_NONE;
}
//don't process the object lists if paused or about to quit to the front end //don't process the object lists if paused or about to quit to the front end
if (!gameUpdatePaused() && intRetVal != INT_QUIT) if (!gameUpdatePaused() && intRetVal != INT_QUIT)
@ -245,43 +190,10 @@ GAMECODE gameLoop(void)
// check all flag positions for duplicate delivery points // check all flag positions for duplicate delivery points
checkFactoryFlags(); checkFactoryFlags();
#endif #endif
if (!editPaused() && gameTicked)
{
// Update abandoned structures
handleAbandonedStructures();
}
//handles callbacks for positioning of DP's //handles callbacks for positioning of DP's
process3DBuilding(); process3DBuilding();
// Update the visibility change stuff
visUpdateLevel();
if (!editPaused() && gameTicked)
{
// Put all droids/structures/features into the grid.
gridReset();
// Check which objects are visible.
processVisibility();
// Update the map.
mapUpdate();
//update the findpath system
fpathUpdate();
// update the cluster system
clusterUpdate();
// update the command droids
cmdDroidUpdate();
if(getDrivingStatus())
{
driveUpdate();
}
}
//ajl. get the incoming netgame messages and process them. //ajl. get the incoming netgame messages and process them.
// FIXME Previous comment is deprecated. multiPlayerLoop does some other weird stuff, but not that anymore. // FIXME Previous comment is deprecated. multiPlayerLoop does some other weird stuff, but not that anymore.
if (bMultiPlayer) if (bMultiPlayer)
@ -289,208 +201,19 @@ GAMECODE gameLoop(void)
multiPlayerLoop(); multiPlayerLoop();
} }
if (!editPaused() && gameTicked) for (unsigned i = 0; i < MAX_PLAYERS; i++)
{ {
for (DROID *psCurr = apsDroidLists[i]; psCurr; psCurr = psCurr->psNext)
fireWaitingCallbacks(); //Now is the good time to fire waiting callbacks (since interpreter is off now)
for(i = 0; i < MAX_PLAYERS; i++)
{
//update the current power available for a player
updatePlayerPower(i);
//set the flag for each player
setHQExists(false, i);
setSatUplinkExists(false, i);
numCommandDroids[i] = 0;
numConstructorDroids[i] = 0;
numDroids[i]=0;
numTransporterDroids[i]=0;
for(psCurr = apsDroidLists[i]; psCurr; psCurr = psNext)
{ {
/* Copy the next pointer - not 100% sure if the droid could get destroyed // Don't copy the next pointer - if droids somehow get destroyed in the graphics rendering loop, who cares if we crash.
but this covers us anyway */ calcDroidIllumination(psCurr);
psNext = psCurr->psNext;
droidUpdate(psCurr);
// update the droid counts
numDroids[i]++;
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
case DROID_TRANSPORTER:
if( (psCurr->psGroup != NULL) )
{
DROID *psDroid = NULL;
numTransporterDroids[i] += psCurr->psGroup->refCount-1;
// and count the units inside it...
for (psDroid = psCurr->psGroup->psList; psDroid != NULL && psDroid != psCurr; psDroid = psDroid->psGrpNext)
{
if (psDroid->droidType == DROID_CYBORG_CONSTRUCT || psDroid->droidType == DROID_CONSTRUCT)
{
numConstructorDroids[i] += 1;
}
if (psDroid->droidType == DROID_COMMAND)
{
numCommandDroids[i] += 1;
}
}
}
break;
default:
break;
}
}
numMissionDroids[i]=0;
for(psCurr = mission.apsDroidLists[i]; psCurr; psCurr = psNext)
{
/* Copy the next pointer - not 100% sure if the droid could
get destroyed but this covers us anyway */
psNext = psCurr->psNext;
missionDroidUpdate(psCurr);
numMissionDroids[i]++;
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
case DROID_TRANSPORTER:
if( (psCurr->psGroup != NULL) )
{
numTransporterDroids[i] += psCurr->psGroup->refCount-1;
}
break;
default:
break;
}
}
for(psCurr = apsLimboDroids[i]; psCurr; psCurr = psNext)
{
/* Copy the next pointer - not 100% sure if the droid could
get destroyed but this covers us anyway */
psNext = psCurr->psNext;
// count the type of units
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
default:
break;
}
}
// FIXME: These for-loops are code duplicationo
/*set this up AFTER droidUpdate so that if trying to building a
new one, we know whether one exists already*/
setLasSatExists(false, i);
for (psCBuilding = apsStructLists[i]; psCBuilding; psCBuilding = psNBuilding)
{
/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway */
psNBuilding = psCBuilding->psNext;
structureUpdate(psCBuilding, false);
//set animation flag
if (psCBuilding->pStructureType->type == REF_HQ &&
psCBuilding->status == SS_BUILT)
{
setHQExists(true, i);
}
if (psCBuilding->pStructureType->type == REF_SAT_UPLINK &&
psCBuilding->status == SS_BUILT)
{
setSatUplinkExists(true, i);
}
//don't wait for the Las Sat to be built - can't build another if one is partially built
if (asWeaponStats[psCBuilding->asWeaps[0].nStat].
weaponSubClass == WSC_LAS_SAT)
{
setLasSatExists(true, i);
}
}
for (psCBuilding = mission.apsStructLists[i]; psCBuilding;
psCBuilding = psNBuilding)
{
/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway. It shouldn't do since its not even on the map!*/
psNBuilding = psCBuilding->psNext;
structureUpdate(psCBuilding, true); // update for mission
if (psCBuilding->pStructureType->type == REF_HQ &&
psCBuilding->status == SS_BUILT)
{
setHQExists(true, i);
}
if (psCBuilding->pStructureType->type == REF_SAT_UPLINK &&
psCBuilding->status == SS_BUILT)
{
setSatUplinkExists(true, i);
}
//don't wait for the Las Sat to be built - can't build another if one is partially built
if (asWeaponStats[psCBuilding->asWeaps[0].nStat].
weaponSubClass == WSC_LAS_SAT)
{
setLasSatExists(true, i);
}
}
}
missionTimerUpdate();
proj_UpdateAll();
for(psCFeat = apsFeatureLists[0]; psCFeat; psCFeat = psNFeat)
{
psNFeat = psCFeat->psNext;
featureUpdate(psCFeat);
}
}
else // if editPaused() or not gameTicked - make sure visual effects are updated
{
for (i = 0; i < MAX_PLAYERS; i++)
{
for(psCurr = apsDroidLists[i]; psCurr; psCurr = psNext)
{
/* Copy the next pointer - not 100% sure if the droid could get destroyed
but this covers us anyway */
psNext = psCurr->psNext;
processVisibilityLevel((BASE_OBJECT *)psCurr);
calcDroidIllumination(psCurr);
}
for (psCBuilding = apsStructLists[i]; psCBuilding; psCBuilding = psNBuilding)
{
/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway */
psNBuilding = psCBuilding->psNext;
processVisibilityLevel((BASE_OBJECT *)psCBuilding);
}
} }
} }
/* update animations */ /* update animations */
animObj_Update(); animObj_Update();
if (gameTicked)
{
objmemUpdate();
}
} }
if (!consolePaused()) if (!consolePaused())
{ {
/* Process all the console messages */ /* Process all the console messages */
@ -501,13 +224,11 @@ GAMECODE gameLoop(void)
scroll(); scroll();
} }
} }
else // paused else // paused
{ {
// Using software cursors (when on) for these menus due to a bug in SDL's SDL_ShowCursor() // Using software cursors (when on) for these menus due to a bug in SDL's SDL_ShowCursor()
wzSetCursor(CURSOR_DEFAULT); wzSetCursor(CURSOR_DEFAULT);
intRetVal = INT_NONE;
if(dragBox3D.status != DRAG_DRAGGING) if(dragBox3D.status != DRAG_DRAGGING)
{ {
scroll(); scroll();
@ -515,7 +236,7 @@ GAMECODE gameLoop(void)
if(InGameOpUp || isInGamePopupUp) // ingame options menu up, run it! if(InGameOpUp || isInGamePopupUp) // ingame options menu up, run it!
{ {
widgval = widgRunScreen(psWScreen); unsigned widgval = widgRunScreen(psWScreen);
intProcessInGameOptions(widgval); intProcessInGameOptions(widgval);
if(widgval == INTINGAMEOP_QUIT_CONFIRM || widgval == INTINGAMEOP_POPUP_QUIT) if(widgval == INTINGAMEOP_QUIT_CONFIRM || widgval == INTINGAMEOP_POPUP_QUIT)
{ {
@ -580,10 +301,8 @@ GAMECODE gameLoop(void)
} }
} }
// Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update.
gameTimeUpdateEnd();
/* Check for quit */ /* Check for quit */
bool quitting = false;
if (intRetVal == INT_QUIT) if (intRetVal == INT_QUIT)
{ {
if (!loop_GetVideoStatus()) if (!loop_GetVideoStatus())
@ -633,17 +352,9 @@ GAMECODE gameLoop(void)
pie_GetResetCounts(&loopPieCount, &loopPolyCount, &loopStateChanges); pie_GetResetCounts(&loopPieCount, &loopPolyCount, &loopStateChanges);
if (fogStatus & FOG_BACKGROUND) if ((fogStatus & FOG_BACKGROUND) && (loopMissionState == LMS_SAVECONTINUE))
{ {
if (loopMissionState == LMS_SAVECONTINUE) pie_SetFogStatus(false);
{
pie_SetFogStatus(false);
clearMode = CLEAR_BLACK;
}
}
else
{
clearMode = CLEAR_BLACK;//force to black 3DFX
} }
if (!quitting) if (!quitting)
@ -676,7 +387,6 @@ GAMECODE gameLoop(void)
break; break;
case LMS_SAVECONTINUE: case LMS_SAVECONTINUE:
// just wait for this to be changed when the new mission starts // just wait for this to be changed when the new mission starts
clearMode = CLEAR_BLACK;
break; break;
case LMS_NEWLEVEL: case LMS_NEWLEVEL:
//nextMissionType = MISSION_NONE; //nextMissionType = MISSION_NONE;
@ -711,6 +421,283 @@ GAMECODE gameLoop(void)
return GAMECODE_CONTINUE; return GAMECODE_CONTINUE;
} }
static void gameStateUpdate()
{
// Can't dump isHumanPlayer, since it causes spurious desynch dumps when players leave.
// TODO isHumanPlayer should probably be synchronised, since the game state seems to depend on it, so there might also be a risk of real desynchs when players leave.
//syncDebug("map = \"%s\", humanPlayers = %d %d %d %d %d %d %d %d", game.map, isHumanPlayer(0), isHumanPlayer(1), isHumanPlayer(2), isHumanPlayer(3), isHumanPlayer(4), isHumanPlayer(5), isHumanPlayer(6), isHumanPlayer(7));
syncDebug("map = \"%s\"", game.map);
// Actually send pending droid orders.
sendQueuedDroidInfo();
sendPlayerGameTime();
gameSRand(gameTime); // Brute force way of synchronising the random number generator, which can't go out of synch.
if (!paused && !scriptPaused() && !editPaused())
{
/* Update the event system */
if (!bInTutorial)
{
eventProcessTriggers(gameTime/SCR_TICKRATE);
}
else
{
eventProcessTriggers(realTime/SCR_TICKRATE);
}
updateScripts();
}
// Update abandoned structures
handleAbandonedStructures();
// Update the visibility change stuff
visUpdateLevel();
// Put all droids/structures/features into the grid.
gridReset();
// Check which objects are visible.
processVisibility();
// Update the map.
mapUpdate();
//update the findpath system
fpathUpdate();
// update the cluster system
clusterUpdate();
// update the command droids
cmdDroidUpdate();
if(getDrivingStatus())
{
driveUpdate();
}
fireWaitingCallbacks(); //Now is the good time to fire waiting callbacks (since interpreter is off now)
for (unsigned i = 0; i < MAX_PLAYERS; i++)
{
//update the current power available for a player
updatePlayerPower(i);
//set the flag for each player
setHQExists(false, i);
setSatUplinkExists(false, i);
numCommandDroids[i] = 0;
numConstructorDroids[i] = 0;
numDroids[i]=0;
numTransporterDroids[i]=0;
DROID *psNext;
for (DROID *psCurr = apsDroidLists[i]; psCurr != NULL; psCurr = psNext)
{
// Copy the next pointer - not 100% sure if the droid could get destroyed but this covers us anyway
psNext = psCurr->psNext;
droidUpdate(psCurr);
// update the droid counts
numDroids[i]++;
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
case DROID_TRANSPORTER:
if( (psCurr->psGroup != NULL) )
{
DROID *psDroid = NULL;
numTransporterDroids[i] += psCurr->psGroup->refCount-1;
// and count the units inside it...
for (psDroid = psCurr->psGroup->psList; psDroid != NULL && psDroid != psCurr; psDroid = psDroid->psGrpNext)
{
if (psDroid->droidType == DROID_CYBORG_CONSTRUCT || psDroid->droidType == DROID_CONSTRUCT)
{
numConstructorDroids[i] += 1;
}
if (psDroid->droidType == DROID_COMMAND)
{
numCommandDroids[i] += 1;
}
}
}
break;
default:
break;
}
}
numMissionDroids[i]=0;
for (DROID *psCurr = mission.apsDroidLists[i]; psCurr != NULL; psCurr = psNext)
{
/* Copy the next pointer - not 100% sure if the droid could
get destroyed but this covers us anyway */
psNext = psCurr->psNext;
missionDroidUpdate(psCurr);
numMissionDroids[i]++;
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
case DROID_TRANSPORTER:
if( (psCurr->psGroup != NULL) )
{
numTransporterDroids[i] += psCurr->psGroup->refCount-1;
}
break;
default:
break;
}
}
for (DROID *psCurr = apsLimboDroids[i]; psCurr != NULL; psCurr = psNext)
{
/* Copy the next pointer - not 100% sure if the droid could
get destroyed but this covers us anyway */
psNext = psCurr->psNext;
// count the type of units
switch (psCurr->droidType)
{
case DROID_COMMAND:
numCommandDroids[i] += 1;
break;
case DROID_CONSTRUCT:
case DROID_CYBORG_CONSTRUCT:
numConstructorDroids[i] += 1;
break;
default:
break;
}
}
// FIXME: These for-loops are code duplicationo
/*set this up AFTER droidUpdate so that if trying to building a
new one, we know whether one exists already*/
setLasSatExists(false, i);
STRUCTURE *psNBuilding;
for (STRUCTURE *psCBuilding = apsStructLists[i]; psCBuilding != NULL; psCBuilding = psNBuilding)
{
/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway */
psNBuilding = psCBuilding->psNext;
structureUpdate(psCBuilding, false);
//set animation flag
if (psCBuilding->pStructureType->type == REF_HQ &&
psCBuilding->status == SS_BUILT)
{
setHQExists(true, i);
}
if (psCBuilding->pStructureType->type == REF_SAT_UPLINK &&
psCBuilding->status == SS_BUILT)
{
setSatUplinkExists(true, i);
}
//don't wait for the Las Sat to be built - can't build another if one is partially built
if (asWeaponStats[psCBuilding->asWeaps[0].nStat].
weaponSubClass == WSC_LAS_SAT)
{
setLasSatExists(true, i);
}
}
for (STRUCTURE *psCBuilding = mission.apsStructLists[i]; psCBuilding != NULL; psCBuilding = psNBuilding)
{
/* Copy the next pointer - not 100% sure if the structure could get destroyed but this covers us anyway. It shouldn't do since its not even on the map!*/
psNBuilding = psCBuilding->psNext;
structureUpdate(psCBuilding, true); // update for mission
if (psCBuilding->pStructureType->type == REF_HQ &&
psCBuilding->status == SS_BUILT)
{
setHQExists(true, i);
}
if (psCBuilding->pStructureType->type == REF_SAT_UPLINK &&
psCBuilding->status == SS_BUILT)
{
setSatUplinkExists(true, i);
}
//don't wait for the Las Sat to be built - can't build another if one is partially built
if (asWeaponStats[psCBuilding->asWeaps[0].nStat].
weaponSubClass == WSC_LAS_SAT)
{
setLasSatExists(true, i);
}
}
}
missionTimerUpdate();
proj_UpdateAll();
FEATURE *psNFeat;
for (FEATURE *psCFeat = apsFeatureLists[0]; psCFeat; psCFeat = psNFeat)
{
psNFeat = psCFeat->psNext;
featureUpdate(psCFeat);
}
objmemUpdate();
// Do completely useless stuff.
if (!isInSync())
{
sendCheck(); // send some pointless checking info if we're doomed anyway
}
// Must end update, since we may or may not have ticked, and some message queue processing code may vary depending on whether it's in an update.
gameTimeUpdateEnd();
}
/* The main game loop */
GAMECODE gameLoop(void)
{
static uint32_t lastFlushTime = 0;
bool didTick = false;
while (true)
{
// Receive NET_BLAH messages.
// Receive GAME_BLAH messages, and if it's time, process exactly as many GAME_BLAH messages as required to be able to tick the gameTime.
recvMessage();
// Update gameTime and graphicsTime, and corresponding deltas. Note that gameTime and graphicsTime pause, if we aren't getting our GAME_GAME_TIME messages.
gameTimeUpdate();
if (deltaGameTime == 0)
{
break; // Not doing a game state update.
}
didTick = true;
ASSERT(!paused && !gameUpdatePaused() && !editPaused(), "Nonsensical pause values.");
syncDebug("Begin game state update, gameTime = %d", gameTime);
gameStateUpdate();
syncDebug("End game state update, gameTime = %d", gameTime);
ASSERT(deltaGraphicsTime == 0, "Shouldn't update graphics and game state at once.");
}
if (didTick || realTime - lastFlushTime < 400u)
{
lastFlushTime = realTime;
NETflush(); // Make sure the game time tick message is really sent over the network, and that we aren't waiting too long to send data.
}
return renderLoop();
}
/* The video playback loop */ /* The video playback loop */
void videoLoop(void) void videoLoop(void)
{ {

View File

@ -871,8 +871,7 @@ bool mapLoad(char *filename, bool preview)
} }
if (!gwNewGateway(x0, y0, x1, y1)) if (!gwNewGateway(x0, y0, x1, y1))
{ {
debug(LOG_ERROR, "%s: Unable to add gateway", filename); debug(LOG_ERROR, "%s: Unable to add gateway %d - dropping it", filename, i);
goto failure;
} }
} }

View File

@ -569,7 +569,7 @@ void addMissionTimerInterface(void)
adding the timer button*/ adding the timer button*/
void addTransporterTimerInterface(void) void addTransporterTimerInterface(void)
{ {
DROID *psDroid, *psTransporter; DROID *psTransporter = NULL;
bool bAddInterface = false; bool bAddInterface = false;
W_CLICKFORM *psForm; W_CLICKFORM *psForm;
@ -577,8 +577,7 @@ void addTransporterTimerInterface(void)
if (mission.ETA >= 0) if (mission.ETA >= 0)
{ {
//check the player has at least one Transporter back at base //check the player has at least one Transporter back at base
psDroid = psTransporter = NULL; for (DROID *psDroid = mission.apsDroidLists[selectedPlayer]; psDroid !=
for (psDroid = mission.apsDroidLists[selectedPlayer]; psDroid !=
NULL; psDroid = psDroid->psNext) NULL; psDroid = psDroid->psNext)
{ {
if (psDroid->droidType == DROID_TRANSPORTER) if (psDroid->droidType == DROID_TRANSPORTER)
@ -587,15 +586,15 @@ void addTransporterTimerInterface(void)
break; break;
} }
} }
if (psDroid) if (psTransporter)
{ {
bAddInterface = true; bAddInterface = true;
//check timer is not already on the screen //check timer is not already on the screen
if (!widgGetFromID(psWScreen, IDTRANTIMER_BUTTON)) if (!widgGetFromID(psWScreen, IDTRANTIMER_BUTTON))
{ {
intAddTransporterTimer(); intAddTransporterTimer();
} }
//set the data for the transporter timer //set the data for the transporter timer
widgSetUserData(psWScreen, IDTRANTIMER_DISPLAY, (void*)psTransporter); widgSetUserData(psWScreen, IDTRANTIMER_DISPLAY, (void*)psTransporter);
@ -1023,11 +1022,6 @@ void placeLimboDroids(void)
} }
psDroid->pos.x = (UWORD)world_coord(droidX); psDroid->pos.x = (UWORD)world_coord(droidX);
psDroid->pos.y = (UWORD)world_coord(droidY); psDroid->pos.y = (UWORD)world_coord(droidY);
if (pickRes == HALF_FREE_TILE )
{
psDroid->pos.x += TILE_UNITS;
psDroid->pos.y += TILE_UNITS;
}
ASSERT(worldOnMap(psDroid->pos.x,psDroid->pos.y), "limbo droid is not on the map"); ASSERT(worldOnMap(psDroid->pos.x,psDroid->pos.y), "limbo droid is not on the map");
psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y); psDroid->pos.z = map_Height(psDroid->pos.x, psDroid->pos.y);
updateDroidOrientation(psDroid); updateDroidOrientation(psDroid);
@ -1380,11 +1374,6 @@ static void processMission(void)
ASSERT(pickRes != NO_FREE_TILE, "processMission: Unable to find a free location" ); ASSERT(pickRes != NO_FREE_TILE, "processMission: Unable to find a free location" );
x = (UWORD)world_coord(droidX); x = (UWORD)world_coord(droidX);
y = (UWORD)world_coord(droidY); y = (UWORD)world_coord(droidY);
if (pickRes == HALF_FREE_TILE )
{
x += TILE_UNITS;
y += TILE_UNITS;
}
droidSetPosition(psDroid, x, y); droidSetPosition(psDroid, x, y);
ASSERT(worldOnMap(psDroid->pos.x,psDroid->pos.y), "the droid is not on the map"); ASSERT(worldOnMap(psDroid->pos.x,psDroid->pos.y), "the droid is not on the map");
updateDroidOrientation(psDroid); updateDroidOrientation(psDroid);
@ -1677,17 +1666,12 @@ void missionDroidUpdate(DROID *psDroid)
// Reset variables in Droids such as order and position // Reset variables in Droids such as order and position
static void missionResetDroids(void) static void missionResetDroids(void)
{ {
UDWORD player;
DROID *psDroid, *psNext;
debug(LOG_SAVE, "called"); debug(LOG_SAVE, "called");
for (player = 0; player < MAX_PLAYERS; player++) for (unsigned int player = 0; player < MAX_PLAYERS; player++)
{ {
for (psDroid = apsDroidLists[player]; psDroid != NULL; psDroid = psNext) for (DROID *psDroid = apsDroidLists[player]; psDroid != NULL; psDroid = psDroid->psNext)
{ {
psNext = psDroid->psNext;
// Reset order - unless constructor droid that is mid-build // Reset order - unless constructor droid that is mid-build
if ((psDroid->droidType == DROID_CONSTRUCT if ((psDroid->droidType == DROID_CONSTRUCT
|| psDroid->droidType == DROID_CYBORG_CONSTRUCT) || psDroid->droidType == DROID_CYBORG_CONSTRUCT)
@ -1709,12 +1693,10 @@ static void missionResetDroids(void)
} }
} }
for (psDroid = apsDroidLists[selectedPlayer]; psDroid != NULL; psDroid = psDroid->psNext) for (DROID *psDroid = apsDroidLists[selectedPlayer]; psDroid != NULL; psDroid = psDroid->psNext)
{ {
bool placed = false; bool placed = false;
psNext = psDroid->psNext;
//for all droids that have never left home base //for all droids that have never left home base
if (psDroid->pos.x == INVALID_XY && psDroid->pos.y == INVALID_XY) if (psDroid->pos.x == INVALID_XY && psDroid->pos.y == INVALID_XY)
{ {
@ -1753,11 +1735,6 @@ static void missionResetDroids(void)
int wx = world_coord(x); int wx = world_coord(x);
int wy = world_coord(y); int wy = world_coord(y);
if (pickRes == HALF_FREE_TILE )
{
wx += TILE_UNITS;
wy += TILE_UNITS;
}
droidSetPosition(psDroid, wx, wy); droidSetPosition(psDroid, wx, wy);
placed = true; placed = true;
} }
@ -1782,11 +1759,6 @@ static void missionResetDroids(void)
int wx = world_coord(x); int wx = world_coord(x);
int wy = world_coord(y); int wy = world_coord(y);
if (pickRes == HALF_FREE_TILE )
{
wx += TILE_UNITS;
wy += TILE_UNITS;
}
droidSetPosition(psDroid, wx, wy); droidSetPosition(psDroid, wx, wy);
placed = true; placed = true;
} }

View File

@ -1942,8 +1942,9 @@ moveCyborgLaunchAnimDone( ANIM_OBJECT *psObj )
"moveCyborgLaunchAnimDone: invalid cyborg pointer" ); "moveCyborgLaunchAnimDone: invalid cyborg pointer" );
/* raise cyborg a little bit so flying - terrible hack - GJ */ /* raise cyborg a little bit so flying - terrible hack - GJ */
psDroid->pos.z++; // Actually, worse than a terrible hack, since it would break synch...
psDroid->sMove.iVertSpeed = CYBORG_VERTICAL_SPEED; //psDroid->pos.z++;
//psDroid->sMove.iVertSpeed = CYBORG_VERTICAL_SPEED;
psDroid->psCurAnim = NULL; psDroid->psCurAnim = NULL;
} }
@ -1957,7 +1958,8 @@ moveCyborgTouchDownAnimDone( ANIM_OBJECT *psObj )
"moveCyborgTouchDownAnimDone: invalid cyborg pointer" ); "moveCyborgTouchDownAnimDone: invalid cyborg pointer" );
psDroid->psCurAnim = NULL; psDroid->psCurAnim = NULL;
psDroid->pos.z = map_Height( psDroid->pos.x, psDroid->pos.y ); // See comment in moveCyborgLaunchAnimDone().
//psDroid->pos.z = map_Height( psDroid->pos.x, psDroid->pos.y );
} }

View File

@ -398,7 +398,7 @@ void loadMapPreview(bool hideInterface)
// load the map data // load the map data
ptr = strrchr(aFileName, '/'); ptr = strrchr(aFileName, '/');
ASSERT(ptr, "this string was supposed to contain a /"); ASSERT_OR_RETURN(, ptr, "this string was supposed to contain a /");
strcpy(ptr, "/game.map"); strcpy(ptr, "/game.map");
if (!mapLoad(aFileName, true)) if (!mapLoad(aFileName, true))
{ {

View File

@ -23,6 +23,7 @@
* Also the selection of disk files.. * Also the selection of disk files..
*/ */
#include "lib/framework/frame.h" #include "lib/framework/frame.h"
#include "lib/framework/wzapp_c.h"
#include "lib/framework/strres.h" #include "lib/framework/strres.h"
#include "lib/widget/button.h" #include "lib/widget/button.h"
#include "lib/widget/widget.h" #include "lib/widget/widget.h"
@ -157,6 +158,8 @@ static char const * M_REQUEST_NP_TIPS[] = { N_("2 players"), N_("3 players"),
#define R_BUT_W 105//112 #define R_BUT_W 105//112
#define R_BUT_H 30 #define R_BUT_H 30
#define HOVER_PREVIEW_TIME 300
bool multiRequestUp = false; //multimenu is up. bool multiRequestUp = false; //multimenu is up.
static unsigned hoverPreviewId; static unsigned hoverPreviewId;
static bool giftsUp[MAX_PLAYERS] = {true}; //gift buttons for player are up. static bool giftsUp[MAX_PLAYERS] = {true}; //gift buttons for player are up.
@ -667,6 +670,9 @@ static void closeMultiRequester(void)
bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValue, bool *isHoverPreview) bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValue, bool *isHoverPreview)
{ {
static unsigned hoverId = 0;
static unsigned hoverStartTime = 0;
if( (id == M_REQUEST_CLOSE) || CancelPressed() ) // user hit close box || hit the cancel key if( (id == M_REQUEST_CLOSE) || CancelPressed() ) // user hit close box || hit the cancel key
{ {
closeMultiRequester(); closeMultiRequester();
@ -678,9 +684,14 @@ bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValu
if (id == 0 && context == MULTIOP_MAP) if (id == 0 && context == MULTIOP_MAP)
{ {
id = widgGetMouseOver(psRScreen); id = widgGetMouseOver(psRScreen);
if (id == hoverPreviewId) if (id != hoverId)
{ {
id = 0; // Don't re-render preview. hoverId = id;
hoverStartTime = wzGetTicks() + HOVER_PREVIEW_TIME;
}
if (id == hoverPreviewId || hoverStartTime > wzGetTicks())
{
id = 0; // Don't re-render preview nor render preview before HOVER_PREVIEW_TIME.
} }
hoverPreview = true; hoverPreview = true;
} }

View File

@ -202,8 +202,6 @@ bool multiPlayerLoop(void)
UDWORD i; UDWORD i;
UBYTE joinCount; UBYTE joinCount;
sendCheck(); // send some checking info if possible
joinCount =0; joinCount =0;
for(i=0;i<MAX_PLAYERS;i++) for(i=0;i<MAX_PLAYERS;i++)
{ {
@ -932,7 +930,6 @@ bool recvResearchStatus(NETQUEUE queue)
// Start the research // Start the research
MakeResearchStarted(pPlayerRes); MakeResearchStarted(pPlayerRes);
psResFacilty->timeStarted = ACTION_START_TIME;
psResFacilty->timeStartHold = 0; psResFacilty->timeStartHold = 0;
} }

View File

@ -650,7 +650,7 @@ bool recvStructureCheck(NETQUEUE queue)
buildStructure(&asStructureStats[j], pS->pos.x, pS->pos.y, pS->player, false); buildStructure(&asStructureStats[j], pS->pos.x, pS->pos.y, pS->player, false);
// Check it is finished // Check it is finished
if (pS && pS->status != SS_BUILT) if (pS->status != SS_BUILT)
{ {
pS->id = ref; pS->id = ref;
pS->status = SS_BUILT; pS->status = SS_BUILT;

View File

@ -1103,8 +1103,7 @@ void orderUpdateDroid(DROID *psDroid)
psDroid->order = DORDER_NONE; psDroid->order = DORDER_NONE;
actionDroid(psDroid, DACTION_NONE); actionDroid(psDroid, DACTION_NONE);
} }
else if (actionReachedBuildPos(psDroid, psDroid->psTarget->pos.x, psDroid->psTarget->pos.y, else if (actionReachedBuildPos(psDroid, psDroid->psTarget->pos.x, psDroid->psTarget->pos.y, ((STRUCTURE *)psDroid->psTarget)->rot.direction, ((STRUCTURE *)psDroid->psTarget)->pStructureType))
((STRUCTURE *)psDroid->psTarget)->pStructureType))
{ {
recycleDroid(psDroid); recycleDroid(psDroid);
} }

View File

@ -177,7 +177,8 @@ static QScriptValue js_queue(QScriptContext *context, QScriptEngine *engine)
void scriptRemoveObject(const BASE_OBJECT *psObj) void scriptRemoveObject(const BASE_OBJECT *psObj)
{ {
for (QHash<int, bindNode>::iterator i = bindings.find(psObj->id); i != bindings.end(); i++) QHash<int, bindNode>::iterator i = bindings.find(psObj->id);
while (i != bindings.end() && i.key() == psObj->id)
{ {
int id = i.key(); int id = i.key();
bindNode node = i.value(); bindNode node = i.value();
@ -188,7 +189,7 @@ void scriptRemoveObject(const BASE_OBJECT *psObj)
args += convMax(psObj, node.engine); args += convMax(psObj, node.engine);
callFunction(node.engine, node.funcName, args); callFunction(node.engine, node.funcName, args);
} }
bindings.erase(i); i = bindings.erase(i);
} }
} }

View File

@ -62,7 +62,20 @@ QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine)
QScriptValue value = convObj(psStruct, engine); QScriptValue value = convObj(psStruct, engine);
value.setProperty("status", (int)psStruct->status, QScriptValue::ReadOnly); value.setProperty("status", (int)psStruct->status, QScriptValue::ReadOnly);
value.setProperty("type", (int)OBJ_STRUCTURE, QScriptValue::ReadOnly); value.setProperty("type", (int)OBJ_STRUCTURE, QScriptValue::ReadOnly);
value.setProperty("stattype", (int)psStruct->pStructureType->type, QScriptValue::ReadOnly); switch (psStruct->pStructureType->type) // don't bleed our source insanities into the scripting world
{
case REF_WALL:
case REF_WALLCORNER:
case REF_GATE:
value.setProperty("stattype", (int)REF_WALL, QScriptValue::ReadOnly);
break;
case REF_BLASTDOOR:
value.setProperty("stattype", (int)REF_DEFENSE, QScriptValue::ReadOnly);
break;
default:
value.setProperty("stattype", (int)psStruct->pStructureType->type, QScriptValue::ReadOnly);
break;
}
return value; return value;
} }
@ -321,7 +334,7 @@ static QScriptValue js_enumStruct(QScriptContext *context, QScriptEngine *engine
static QScriptValue js_enumFeature(QScriptContext *context, QScriptEngine *engine) static QScriptValue js_enumFeature(QScriptContext *context, QScriptEngine *engine)
{ {
QList<FEATURE *> matches; QList<FEATURE *> matches;
int looking = context->argument(1).toInt32(); int looking = context->argument(0).toInt32();
QString statsName = statsName = context->argument(1).toString(); QString statsName = statsName = context->argument(1).toString();
SCRIPT_ASSERT(context, looking < MAX_PLAYERS && looking >= -1, "Looking player index out of range: %d", looking); SCRIPT_ASSERT(context, looking < MAX_PLAYERS && looking >= -1, "Looking player index out of range: %d", looking);
for (FEATURE *psFeat = apsFeatureLists[0]; psFeat; psFeat = psFeat->psNext) for (FEATURE *psFeat = apsFeatureLists[0]; psFeat; psFeat = psFeat->psNext)
@ -501,6 +514,17 @@ static QScriptValue js_structureIdle(QScriptContext *context, QScriptEngine *)
return QScriptValue(structureIdle(psStruct)); return QScriptValue(structureIdle(psStruct));
} }
static QScriptValue js_removeStruct(QScriptContext *context, QScriptEngine *)
{
QScriptValue structVal = context->argument(0);
int id = structVal.property("id").toInt32();
int player = structVal.property("player").toInt32();
STRUCTURE *psStruct = IdToStruct(id, player);
SCRIPT_ASSERT(context, psStruct, "No such structure id %d belonging to player %d", id, player);
removeStruct(psStruct, true);
return QScriptValue();
}
// TODO, should cover scrShowConsoleText, scrAddConsoleText, scrTagConsoleText and scrConsole // TODO, should cover scrShowConsoleText, scrAddConsoleText, scrTagConsoleText and scrConsole
static QScriptValue js_console(QScriptContext *context, QScriptEngine *engine) static QScriptValue js_console(QScriptContext *context, QScriptEngine *engine)
{ {
@ -1041,6 +1065,7 @@ bool registerFunctions(QScriptEngine *engine)
engine->globalObject().setProperty("makeComponentAvailable", engine->newFunction(js_makeComponentAvailable)); engine->globalObject().setProperty("makeComponentAvailable", engine->newFunction(js_makeComponentAvailable));
engine->globalObject().setProperty("enableComponent", engine->newFunction(js_enableComponent)); engine->globalObject().setProperty("enableComponent", engine->newFunction(js_enableComponent));
engine->globalObject().setProperty("allianceExistsBetween", engine->newFunction(js_allianceExistsBetween)); engine->globalObject().setProperty("allianceExistsBetween", engine->newFunction(js_allianceExistsBetween));
engine->globalObject().setProperty("removeStruct", engine->newFunction(js_removeStruct));
// Set some useful constants // Set some useful constants
engine->globalObject().setProperty("DORDER_ATTACK", DORDER_ATTACK, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DORDER_ATTACK", DORDER_ATTACK, QScriptValue::ReadOnly | QScriptValue::Undeletable);
@ -1073,20 +1098,37 @@ bool registerFunctions(QScriptEngine *engine)
engine->globalObject().setProperty("BUILT", SS_BUILT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BUILT", SS_BUILT, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("BEING_DEMOLISHED", SS_BEING_DEMOLISHED, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("BEING_DEMOLISHED", SS_BEING_DEMOLISHED, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("DROID_CONSTRUCT", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID_CONSTRUCT", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_HQ", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("HQ", REF_HQ, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_FACTORY", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("FACTORY", REF_FACTORY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_POWER_GEN", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("POWER_GEN", REF_POWER_GEN, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_RESOURCE_EXTRACTOR", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESOURCE_EXTRACTOR", REF_RESOURCE_EXTRACTOR, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_DEFENSE", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DEFENSE", REF_DEFENSE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_WALL", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("WALL", REF_WALL, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_RESEARCH", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("RESEARCH", REF_RESEARCH, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_REPAIR_FACILITY", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("REPAIR_FACILITY", REF_REPAIR_FACILITY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_CYBORG_FACTORY", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("CYBORG_FACTORY", REF_CYBORG_FACTORY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_VTOL_FACTORY", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("VTOL_FACTORY", REF_VTOL_FACTORY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_REARM_PAD", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("REARM_PAD", REF_REARM_PAD, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_SAT_UPLINK", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("SAT_UPLINK", REF_SAT_UPLINK, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_GATE", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("GATE", REF_GATE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("REF_COMMAND_CONTROL", DROID_CONSTRUCT, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("COMMAND_CONTROL", REF_COMMAND_CONTROL, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("EASY", DIFFICULTY_EASY, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("MEDIUM", DIFFICULTY_MEDIUM, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("HARD", DIFFICULTY_HARD, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("INSANE", DIFFICULTY_INSANE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
// Static knowledge about players
QScriptValue playerData = engine->newArray(game.maxPlayers);
for (int i = 0; i < game.maxPlayers; i++)
{
QScriptValue vector = engine->newObject();
vector.setProperty("difficulty", NetPlay.players[i].difficulty, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("colour", NetPlay.players[i].colour, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("position", NetPlay.players[i].position, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("team", NetPlay.players[i].team, QScriptValue::ReadOnly | QScriptValue::Undeletable);
playerData.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable);
}
engine->globalObject().setProperty("playerData", playerData, QScriptValue::ReadOnly | QScriptValue::Undeletable);
// Static map knowledge about start positions // Static map knowledge about start positions
QScriptValue startPositions = engine->newArray(game.maxPlayers); QScriptValue startPositions = engine->newArray(game.maxPlayers);
@ -1105,8 +1147,8 @@ bool registerFunctions(QScriptEngine *engine)
vector.setProperty("y", map_coord(derricks[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("y", map_coord(derricks[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable);
derrickPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); derrickPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable);
} }
engine->globalObject().setProperty("startPositions", startPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("derrickPositions", derrickPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("derrickPositions", derrickPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("startPositions", startPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable);
return true; return true;
} }

View File

@ -1257,10 +1257,6 @@ void releaseResearch(STRUCTURE *psBuilding, QUEUE_MODE mode)
if (psResFac->psSubject && psResFac->timeStartHold) if (psResFac->psSubject && psResFac->timeStartHold)
{ {
//adjust the start time for the current subject //adjust the start time for the current subject
if (psResFac->timeStarted != ACTION_START_TIME)
{
psResFac->timeStarted += (gameTime - psResFac->timeStartHold);
}
psResFac->timeStartHold = 0; psResFac->timeStartHold = 0;
} }
} }
@ -1322,16 +1318,13 @@ void cancelResearch(STRUCTURE *psBuilding, QUEUE_MODE mode)
} }
//check if waiting to accrue power //check if waiting to accrue power
if (psResFac->timeStarted == ACTION_START_TIME) if (pPlayerRes->currentPoints == 0)
{ {
// Reset this topic as not having been researched // Reset this topic as not having been researched
ResetResearchStatus(pPlayerRes); ResetResearchStatus(pPlayerRes);
} }
else else
{ {
/* store the points - need to keep this so can add points after the topic has been cancelled and restarted */
pPlayerRes->currentPoints += (psResFac->researchPoints * (gameTime - psResFac->timeStarted)) / GAME_TICKS_PER_SEC;
// Set the researched flag // Set the researched flag
MakeResearchCancelled(pPlayerRes); MakeResearchCancelled(pPlayerRes);
} }
@ -1842,11 +1835,10 @@ bool enableResearch(RESEARCH *psResearch, UDWORD player)
'give' the results to the reward player*/ 'give' the results to the reward player*/
void researchReward(UBYTE losingPlayer, UBYTE rewardPlayer) void researchReward(UBYTE losingPlayer, UBYTE rewardPlayer)
{ {
UDWORD topicIndex, researchPoints, rewardID; UDWORD topicIndex = 0, researchPoints = 0, rewardID = 0;
STRUCTURE *psStruct; STRUCTURE *psStruct;
RESEARCH_FACILITY *psFacility; RESEARCH_FACILITY *psFacility;
topicIndex = researchPoints = rewardID = 0;
//look through the losing players structures to find a research facility //look through the losing players structures to find a research facility
for (psStruct = apsStructLists[losingPlayer]; psStruct != NULL; psStruct = for (psStruct = apsStructLists[losingPlayer]; psStruct != NULL; psStruct =
psStruct->psNext) psStruct->psNext)

View File

@ -1169,7 +1169,6 @@ static BASE_OBJECT *scrTargetInArea(SDWORD tarPlayer, SDWORD visPlayer, SDWORD t
{ {
BASE_OBJECT *psTarget, *psCurr; BASE_OBJECT *psTarget, *psCurr;
SDWORD temp; SDWORD temp;
bool bVisCheck;
UDWORD tarMask; UDWORD tarMask;
TARGET_MASK getTargetMask; TARGET_MASK getTargetMask;
TARGET_PREF targetPriority; TARGET_PREF targetPriority;
@ -1195,17 +1194,6 @@ static BASE_OBJECT *scrTargetInArea(SDWORD tarPlayer, SDWORD visPlayer, SDWORD t
y1 = temp; y1 = temp;
} }
// see if a visibility check is required and for which player
if (visPlayer < 0 || visPlayer >= MAX_PLAYERS)
{
bVisCheck = false;
}
else
{
bVisCheck = true;
}
bVisCheck = false;
// see which target type to use // see which target type to use
switch (tarType) switch (tarType)
{ {
@ -1231,8 +1219,7 @@ static BASE_OBJECT *scrTargetInArea(SDWORD tarPlayer, SDWORD visPlayer, SDWORD t
psTarget = NULL; psTarget = NULL;
for(; psCurr; psCurr=psCurr->psNext) for(; psCurr; psCurr=psCurr->psNext)
{ {
if ((!bVisCheck || psCurr->visible[visPlayer]) && if ((cluster == 0 || psCurr->cluster == cluster) &&
(cluster == 0 || psCurr->cluster == cluster) &&
((SDWORD)psCurr->pos.x >= x1) && ((SDWORD)psCurr->pos.x >= x1) &&
((SDWORD)psCurr->pos.x <= x2) && ((SDWORD)psCurr->pos.x <= x2) &&
((SDWORD)psCurr->pos.y >= y1) && ((SDWORD)psCurr->pos.y >= y1) &&

View File

@ -3391,22 +3391,14 @@ bool scrAnyStructButWallsLeft(void)
} }
//check the players list for any structures //check the players list for any structures
structuresLeft = true; structuresLeft = false;
if (apsStructLists[player] == NULL) for (psCurr = apsStructLists[player]; psCurr != NULL; psCurr = psCurr->psNext)
{ {
structuresLeft = false; if (psCurr->pStructureType->type != REF_WALL && psCurr->pStructureType->
}
else
{
structuresLeft = false;
for (psCurr = apsStructLists[player]; psCurr != NULL; psCurr = psCurr->psNext)
{
if (psCurr->pStructureType->type != REF_WALL && psCurr->pStructureType->
type != REF_WALLCORNER) type != REF_WALLCORNER)
{ {
structuresLeft = true; structuresLeft = true;
break; break;
}
} }
} }
@ -7327,7 +7319,6 @@ bool scrNumResearchLeft(void)
top = -1; top = -1;
cur = 0; //start with first index's PR cur = 0; //start with first index's PR
tempIndex = -1;
while(true) //do while(true) //do
{ {
if (cur >= asResearch[index].pPRList.size()) //this one has no PRs or end of PRs reached if (cur >= asResearch[index].pPRList.size()) //this one has no PRs or end of PRs reached
@ -9808,7 +9799,6 @@ bool scrPursueResearch(void)
top = -1; top = -1;
cur = 0; //start with first index's PR cur = 0; //start with first index's PR
tempIndex = -1;
while(true) //do while(true) //do
{ {
//DbgMsg("Going on with %d, numPR: %d, %s", index, asResearch[index].pPRList.size(), asResearch[index].pName); //DbgMsg("Going on with %d, numPR: %d, %s", index, asResearch[index].pPRList.size(), asResearch[index].pName);

View File

@ -777,9 +777,10 @@ bool scrValDefSave(INTERP_VAL *psVal, WzConfig &ini)
break; break;
case ST_RESEARCH: case ST_RESEARCH:
psResearch = (RESEARCH *)psVal->v.oval; psResearch = (RESEARCH *)psVal->v.oval;
if (psResearch) if (psResearch && psResearch->pName[0] != '\0')
{ {
ini.setValue("data", QString(psResearch->pName)); ini.setValue("data", QString(psResearch->pName));
ASSERT(psResearch == getResearch(psResearch->pName), "Research %s not found!", psResearch->pName);
} }
break; break;
case ST_GROUP: case ST_GROUP:
@ -1005,10 +1006,11 @@ bool scrValDefLoad(INTERP_VAL *psVal, WzConfig &ini)
psVal->v.oval = NULL; psVal->v.oval = NULL;
if (ini.contains("data")) if (ini.contains("data"))
{ {
psVal->v.oval = (void*)getResearch(ini.value("data").toString().toAscii().constData()); QString research = ini.value("data").toString();
if (psVal->v.oval == NULL) if (!research.isEmpty())
{ {
debug(LOG_FATAL, "Could not find research"); psVal->v.oval = (void*)getResearch(research.toUtf8().constData());
ASSERT_OR_RETURN(false, psVal->v.oval, "Could not find research %s", research.toUtf8().constData());
} }
} }
break; break;

View File

@ -72,8 +72,8 @@ struct SEQTEXT
char pText[MAX_STR_LENGTH]; char pText[MAX_STR_LENGTH];
UDWORD x; UDWORD x;
UDWORD y; UDWORD y;
UDWORD startFrame; double startTime;
UDWORD endFrame; double endTime;
bool bSubtitle; bool bSubtitle;
}; };
@ -281,7 +281,7 @@ bool seq_UpdateFullScreenVideo(int *pbClear)
unsigned int subMax = SUBTITLE_BOX_MIN + D_H2; unsigned int subMax = SUBTITLE_BOX_MIN + D_H2;
//get any text lines over bottom of the video //get any text lines over bottom of the video
unsigned int realFrame = seq_GetFrameNumber(); double realTime = seq_GetFrameTime();
for (i = 0; i < MAX_TEXT_OVERLAYS; i++) for (i = 0; i < MAX_TEXT_OVERLAYS; i++)
{ {
SEQTEXT seqtext = aSeqList[currentPlaySeq].aText[i]; SEQTEXT seqtext = aSeqList[currentPlaySeq].aText[i];
@ -289,7 +289,7 @@ bool seq_UpdateFullScreenVideo(int *pbClear)
{ {
if (seqtext.bSubtitle) if (seqtext.bSubtitle)
{ {
if (((realFrame >= seqtext.startFrame) && (realFrame <= seqtext.endFrame)) || if (((realTime >= seqtext.startTime) && (realTime <= seqtext.endTime)) ||
aSeqList[currentPlaySeq].bSeqLoop) //if its a looped video always draw the text aSeqList[currentPlaySeq].bSeqLoop) //if its a looped video always draw the text
{ {
if (subMin > seqtext.y && seqtext.y > SUBTITLE_BOX_MIN) if (subMin > seqtext.y && seqtext.y > SUBTITLE_BOX_MIN)
@ -303,7 +303,7 @@ bool seq_UpdateFullScreenVideo(int *pbClear)
} }
} }
if (realFrame >= seqtext.endFrame && realFrame < seqtext.endFrame) if (realTime >= seqtext.endTime && realTime < seqtext.endTime)
{ {
if (pbClear != NULL) if (pbClear != NULL)
{ {
@ -333,14 +333,14 @@ bool seq_UpdateFullScreenVideo(int *pbClear)
//call sequence player to download last frame //call sequence player to download last frame
stillPlaying = seq_Update(); stillPlaying = seq_Update();
//print any text over the video //print any text over the video
realFrame = seq_GetFrameNumber();//textFrame + 1; realTime = seq_GetFrameTime();
for (i = 0; i < MAX_TEXT_OVERLAYS; i++) for (i = 0; i < MAX_TEXT_OVERLAYS; i++)
{ {
SEQTEXT currentText = aSeqList[currentPlaySeq].aText[i]; SEQTEXT currentText = aSeqList[currentPlaySeq].aText[i];
if (currentText.pText[0] != '\0') if (currentText.pText[0] != '\0')
{ {
if (((realFrame >= currentText.startFrame) && (realFrame <= currentText.endFrame)) || if (((realTime >= currentText.startTime) && (realTime <= currentText.endTime)) ||
(aSeqList[currentPlaySeq].bSeqLoop)) //if its a looped video always draw the text (aSeqList[currentPlaySeq].bSeqLoop)) //if its a looped video always draw the text
{ {
if (bMoreThanOneSequenceLine) if (bMoreThanOneSequenceLine)
@ -399,7 +399,7 @@ bool seq_StopFullScreenVideo(void)
} }
// add a string at x,y or add string below last line if x and y are 0 // add a string at x,y or add string below last line if x and y are 0
bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, SDWORD startFrame, SDWORD endFrame, SEQ_TEXT_POSITIONING textJustification) bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, double startTime, double endTime, SEQ_TEXT_POSITIONING textJustification)
{ {
SDWORD sourceLength, currentLength; SDWORD sourceLength, currentLength;
char* currentText; char* currentText;
@ -476,8 +476,8 @@ bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, SDWO
} }
//set start and finish times for the objects //set start and finish times for the objects
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].startFrame = startFrame; aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].startTime = startTime;
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].endFrame = endFrame; aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].endTime = endTime;
aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].bSubtitle = textJustification; aSeqList[currentSeq].aText[aSeqList[currentSeq].currentText].bSubtitle = textJustification;
aSeqList[currentSeq].currentText++; aSeqList[currentSeq].currentText++;
@ -494,7 +494,7 @@ bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, SDWO
{ {
textJustification = SEQ_TEXT_POSITION; textJustification = SEQ_TEXT_POSITION;
} }
seq_AddTextForVideo(&pText[currentLength + 1], 0, 0, startFrame, endFrame, textJustification); seq_AddTextForVideo(&pText[currentLength + 1], 0, 0, startTime, endTime, textJustification);
} }
return true; return true;
} }
@ -505,7 +505,8 @@ static bool seq_AddTextFromFile(const char *pTextName, SEQ_TEXT_POSITIONING text
char aTextName[MAX_STR_LENGTH]; char aTextName[MAX_STR_LENGTH];
char *pTextBuffer, *pCurrentLine, *pText; char *pTextBuffer, *pCurrentLine, *pText;
UDWORD fileSize; UDWORD fileSize;
SDWORD xOffset, yOffset, startFrame, endFrame; SDWORD xOffset, yOffset;
double startTime, endTime;
const char *seps = "\n"; const char *seps = "\n";
// NOTE: The original game never had a fullscreen mode for FMVs on >640x480 screens. // NOTE: The original game never had a fullscreen mode for FMVs on >640x480 screens.
@ -527,7 +528,7 @@ static bool seq_AddTextFromFile(const char *pTextName, SEQ_TEXT_POSITIONING text
{ {
if (*pCurrentLine != '/') if (*pCurrentLine != '/')
{ {
if (sscanf(pCurrentLine,"%d %d %d %d", &xOffset, &yOffset, &startFrame, &endFrame) == 4) if (sscanf(pCurrentLine,"%d %d %lf %lf", &xOffset, &yOffset, &startTime, &endTime) == 4)
{ {
// Since all the positioning was hardcoded to specific values, we now calculate the // Since all the positioning was hardcoded to specific values, we now calculate the
// ratio of our screen, compared to what the game expects and multiply that to x, y. // ratio of our screen, compared to what the game expects and multiply that to x, y.
@ -545,7 +546,7 @@ static bool seq_AddTextFromFile(const char *pTextName, SEQ_TEXT_POSITIONING text
ASSERT(pText != NULL, "error parsing text file"); ASSERT(pText != NULL, "error parsing text file");
if (pText != NULL) if (pText != NULL)
{ {
seq_AddTextForVideo(_(&pText[1]), xOffset, yOffset, startFrame, endFrame, textJustification); seq_AddTextForVideo(_(&pText[1]), xOffset, yOffset, startTime, endTime, textJustification);
} }
} }
} }

View File

@ -76,7 +76,7 @@ extern bool seq_StopFullScreenVideo(void);
//control //control
extern bool seq_GetVideoSize(SDWORD* pWidth, SDWORD* pHeight); extern bool seq_GetVideoSize(SDWORD* pWidth, SDWORD* pHeight);
//text //text
extern bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, SDWORD startTime, SDWORD endTime, SEQ_TEXT_POSITIONING textJustification); extern bool seq_AddTextForVideo(const char* pText, SDWORD xOffset, SDWORD yOffset, double startTime, double endTime, SEQ_TEXT_POSITIONING textJustification);
//clear the sequence list //clear the sequence list
extern void seq_ClearSeqList(void); extern void seq_ClearSeqList(void);
//add a sequence to the list to be played //add a sequence to the list to be played

Some files were not shown because too many files have changed in this diff Show More