Compare commits

...

65 Commits

Author SHA1 Message Date
George Sokianos 877c78509d Prepare MorphOS release 2022-09-19 21:00:29 +01:00
George Sokianos 2672b953a3 A lot of changes for speed up, code clean up, new release preparation and MorphOS code added 2022-09-19 19:29:41 +01:00
George Sokianos d7363ad95f Some more changes preparing the release 2022-08-13 13:57:37 +01:00
George Sokianos 575b701190 Changes to compile and work under AmigaOS 4 2022-08-13 10:20:11 +01:00
Steve 1a684a9737 Report success for deleting files that don't exist! (save game regression). 2019-12-02 07:47:16 +00:00
Steve 13c8c9c05a Windows and Mac make files. 2019-12-01 11:57:04 +00:00
Steve 2fa40d8933 Delete temporary files before attempting to rename (Windows and some Unix fixes). 2019-12-01 11:56:49 +00:00
Steve e8a8e87666 Removed Windows and Mac builds. Too buggy in cross compile. 2019-06-02 17:32:26 +01:00
Steve 1093c16ed0 Atlas update. 2019-06-02 16:13:34 +01:00
Steve 9717047d47 Faster map loading. 2019-01-19 13:19:23 +00:00
Steve a064e3ed4c Don't use atlas for clouds. Helps to eliminate texture seam. 2018-12-28 11:00:45 +00:00
Steve a7310e43b1 Text rendering tweaks. 2018-12-23 15:32:33 +00:00
Steve fc0bcc998c Replaced cached text with font atlas. 2018-12-22 22:46:38 +00:00
Steve 86be9a25b9 Start of resolution updates. 2018-12-22 21:53:19 +00:00
Steve 9acb52163c Updated links from stephenjsweeney.com to parallelrealities.co.uk. 2018-07-17 09:17:01 +01:00
Steve 9bceef8044 Cap frame rate at 60fps. 2018-07-07 07:00:55 +01:00
Steve 08ef2920cf Don't treat warnings as errors. 2018-07-07 07:00:45 +01:00
Steve f6fd6b918d v1.1.1 2018-07-07 07:00:33 +01:00
Steve 986cb78d7b Freeplay manual updates. 2018-05-18 07:54:41 +01:00
Steve 49abba5faa Use a . in $VERSION.$REVISION instead of a -. 2018-05-18 07:42:14 +01:00
Steve f9064d26f7 Don't force mirroring in world test. 2018-05-16 08:16:54 +01:00
Steve c6aa5f60aa Additional mission configuration info text. 2018-05-16 08:06:52 +01:00
Steve 021a02f8e9 Correctly adjust teleporter destination when mirroring. 2018-05-16 08:06:37 +01:00
Steve 24f677236a Removed all objectives tweak, replaced with No Doors. Tweaks to item and pushblock mirroring. Other minor mission tweak fixes. 2018-05-15 08:32:16 +01:00
Steve 1ad4746a27 Merge branch 'develop' into plus 2018-05-15 07:46:53 +01:00
Steve 7598af42a0 GCC compile fix for fadeAmount not being initialized. 2018-05-15 07:37:27 +01:00
Steve 0395d25594 Use PLUS_ALL_OBJS to test for required objectives. 2018-05-14 08:32:45 +01:00
Steve 455db3d077 Correctly mirror doors in mirror mode. 2018-05-14 08:23:54 +01:00
Steve 230d28cef7 Mirror world tweaks. 2018-05-13 17:25:00 +01:00
Steve 0c631edd09 Start of map mirroring. 2018-05-13 08:59:30 +01:00
Steve 05e7fc7cad Updated mission config settings. 2018-05-12 11:50:49 +01:00
Steve 7eefeeed86 Set language size to be MAX_DESCRIPTION_LENGTH, not MAX_LINE_LENGTH. 2018-05-11 08:42:04 +01:00
Steve 181fc83632 Start of custom mission plus settings. 2018-05-11 08:09:15 +01:00
Steve 60d8020c4e Game plus tweaks. 2018-05-02 07:55:55 +01:00
Steve 693ed5f032 Exit if we try to load corrupt data (although we shouldn't really get this far). 2018-05-01 18:17:16 +01:00
Steve cdc69cc6a5 Various Game Plus tweaks. 2018-05-01 18:15:56 +01:00
Steve 3ae8a2a717 Give enemies more health in Plus mode. 2018-05-01 08:40:57 +01:00
Steve 6fe72e4b2a Start of experimental Mission Plus mode. 2018-05-01 08:38:46 +01:00
Steve 220525d6f8 Removed references to trophy screenshot, as this feature no longer exists. 2018-04-30 08:36:51 +01:00
Steve 224952a962 Check for possible corrupt save files and prevent loading. 2018-04-29 07:47:37 +01:00
Steve 3a99531a04 Don't include missions complete in % stats for save label. Correctly handle %. 2018-04-28 16:09:24 +01:00
Steve 01448698ad Item to reset items that are stuck in walls are mission start. 2018-04-28 15:55:01 +01:00
Steve 47ae458edd Memory corruption fix. 2018-04-28 09:50:01 +01:00
Steve bb054c28b4 v1.0.3 2018-04-28 09:46:26 +01:00
Steve cd8ee71c30 Save grenade combo value to correct stat slot. 2018-04-27 18:22:32 +01:00
Steve c4efe60abd Don't allow laser traps to keep victims alive indefinitely. 2018-04-26 09:07:32 +01:00
Steve 9bafce978f Don't save Teeka - there is never an instance in the game where he needs to be persisted. 2018-04-25 18:15:23 +01:00
Steve ceaced512f If Bob was stunned when the game is saving, set him back to normal facing so we don't error. 2018-04-25 08:17:49 +01:00
Steve 9c1b39179d Tidied up headers. 2018-04-25 07:56:06 +01:00
Steve 5120b6586b Updated POWs to MIAs. 2018-04-24 19:04:35 +01:00
Steve d4f310119f Centre bullets more inside shooter. 2018-04-24 19:04:08 +01:00
Steve 73e0e4b17a Attempt to save the game and world data atomically. 2018-04-24 08:27:42 +01:00
Steve 67a6ad5422 Don't hardcode Tab in the message. 2018-04-24 08:27:16 +01:00
Steve d642a72e3c Merge remote-tracking branch 'origin/master' into develop 2018-04-24 07:23:48 +01:00
Stephen J Sweeney 5b499b7be7
Merge pull request #10 from LeifAndersen/fixtext
Change prose since no longer on a touch screen.
2018-04-24 07:23:17 +01:00
Steve 5f212282b2 Added grenade combo counter HUD message and gameplay stat. 2018-04-24 07:17:05 +01:00
Leif Andersen 2b576c402b
Change prose since no longer on a touch screen. 2018-04-24 00:34:47 -04:00
Steve fab49ae250 Added missing Linux .desktop file. 2018-04-23 07:10:21 +01:00
Steve 7851495d28 v1.0.2. 2018-04-22 18:47:44 +01:00
Steve 38c47e2809 (some corrections from previous merge) 2018-04-22 18:47:10 +01:00
Steve dd521bdb6d Merge remote-tracking branch 'origin/master' into develop 2018-04-22 18:44:53 +01:00
Stephen J Sweeney d359b99e98
Merge pull request #7 from noahadvs/master
Change "blobWarsAttrition" to "blobwarsAttrition"
2018-04-22 18:44:15 +01:00
Noah Davis 85e66da367 Fix naming inconsistency
All instances of 'blobWarsAttrition' have been changed to 'blobwarsAttrition to match the name of the GitHub repository.

This also fixes an issue with the makefile for Unix-like systems with case sensitive file systems where it could not 'make install' because of the naming inconsistency.
2018-04-22 04:43:49 -04:00
Steve c2b2b86710 Merge branch 'paths' into develop 2018-04-22 09:11:25 +01:00
Steve f5bdb5e59a Use malloc to create some sprintf string values (long paths). 2018-04-21 11:54:06 +01:00
251 changed files with 4014 additions and 2836 deletions

4
.gitignore vendored
View File

@ -5,4 +5,6 @@ blobwarsAttrition
*.o
.DS_Store
dist/*
/blobWarsAttrition.exe
/blobwarsAttrition.exe
/.errors
build

53
README-Amiga.md Normal file
View File

@ -0,0 +1,53 @@
# Blob Wars : Attrition
This is the port of the Blob Wars Attrition 1.2.2 for the AmigaOS 4 and
MorphOS.
The AmigaOS 4 versions is tested and runs well on X5000/40. Also I tested
it on microAmigaOne but the lack of graphics memory (32MB total) makes it
really slow.
The MorphOS version was tested on PowerBook G4 and runs pretty fine and
quickly.
I'd love to hear how it works on your system.
### Installation
This archive does not contain any data files. In order to play the game, you
will need to purchase the data. You can do so here:
http://www.parallelrealities.co.uk/games/attrition/#purchase
To install it, extract all the files from the bought Linux archive
(blobwarsAttrition-1.2.2.linux-x86.tar.gz) anywhere at you hard disk
and copy over all the files from this archive. A requester will show up
to replace the blobwarsAttrition binary, which you need to confirm.
I do not recommend to use the demo data provided from the official website,
because they do not work correctly.
It is recommended to have the following SDL2 options enabled at its prefs:
- Driver: opengl/opengl2 depending your gfx card and the drivers you have
installed in your system
- Batching Mode: enabled
### Support
If you like what I am doing and my ports and you would like to support me,
and my future releases please visit https://ko-fi.com/walkero where you
can find all the latest updates by me and you can donate.
### Changelog
1.2.2r2 (2022-09-19)
* Did a few changes at the code that speeds up the game a lot
* Removed the white shadow from texts in some renderers
* Changed the freetype library with the latest version
* Removed the debug info at the start of the game
* MorphOS version released
* Some code cleanup at the repo
1.2.2r1 (2022-08-13)
* First release

View File

@ -2,7 +2,7 @@
Blob Wars : Attrition is a 2D mission and objective-based platform game. It is the third game in the Blob Wars series.
The develop branch on GitHub (https://github.com/stephenjsweeney/blobWarsAttrition/tree/develop) is where all the dev work happens. Stable(ish) releases will go in to master (https://github.com/stephenjsweeney/blobWarsAttrition/tree/master).
The develop branch on GitHub (https://github.com/stephenjsweeney/blobwarsAttrition/tree/develop) is where all the dev work happens. Stable(ish) releases will go in to master (https://github.com/stephenjsweeney/blobwarsAttrition/tree/master).
The source code of this game (everything under the src directory) is licensed under the GPL. www.gnu.org/licenses/gpl-3.0.en.html
@ -10,13 +10,13 @@ The source code of this game (everything under the src directory) is licensed un
This repo does not contain any data files (maps, sprite definitions, etc). In order to play the game, you will need to purchase the data. You can do so here:
http://www.stephenjsweeney.com/games/attrition/#purchase
http://www.parallelrealities.co.uk/games/attrition/#purchase
Demo data files are also available. See further below for more details.
### DATA INSTALLATION
The data folder should be placed alongside the gfx, sound, and music folders, so that the game can access it. By default, the "make install" step will place the data files into /opt/blobWarsAttrition. This is where you should copy the data folder, in order for the game to work. Or, after building, you can run the game in place.
The data folder should be placed alongside the gfx, sound, and music folders, so that the game can access it. By default, the "make install" step will place the data files into /opt/blobwarsAttrition. This is where you should copy the data folder, in order for the game to work. Or, after building, you can run the game in place.
### DEMO DATA
@ -24,15 +24,15 @@ Demo data files are also available and can be installed in the same way. The dem
You can download the demo data here, as either a zip or a gzip:
http://www.stephenjsweeney.com/downloads/blobWarsAttrition/blobWarsAttrition-demo-data.zip
http://www.parallelrealities.co.uk/downloads/blobWarsAttrition/blobWarsAttrition-demo-data.zip
http://www.stephenjsweeney.com/downloads/blobWarsAttrition/blobWarsAttrition-demo-data.tar.gz
http://www.parallelrealities.co.uk/downloads/blobWarsAttrition/blobWarsAttrition-demo-data.tar.gz
If you upgrade from the demo data files to the commercial ones, you should start the game from scratch, to prevent issues with the persistent world.
## SCREENSHOTS
Screenshots from various versions can be found here: https://github.com/stephenjsweeney/blobWarsAttrition/tree/master/dev/screenshots
Screenshots from various versions can be found here: https://github.com/stephenjsweeney/blobwarsAttrition/tree/master/dev/screenshots
## CREDITS

View File

@ -1,11 +0,0 @@
#!/bin/bash -e
VERSION=`egrep 'VERSION = ([0-9.+])' ../common.mk | awk '{print $3}'`
REVISION=`egrep 'REVISION = ([0-9.+])' ../common.mk | awk '{print $3}'`
mkdir -p ../dist
rm -rf ../dist/*
linux/build.sh $VERSION $REVISION
win32/build.sh $VERSION $REVISION

View File

@ -1,19 +0,0 @@
#!/bin/bash -e
cd `dirname $0`
BUILDROOT="build/linux"
cd ../..
VERSION=$1
REVISION=$2
make clean
make src-dist
make clean
make LOCALE_DIR=locale
make dist
rm -rf blobWarsAttrition

View File

@ -1,39 +0,0 @@
#!/bin/bash -e
cd `dirname $0`
BUILDROOT="build/win32"
cd ../..
VERSION=$1
REVISION=$2
FOLDER="blobWarsAttrition-$1.$2"
OUT="$BUILDROOT/$FOLDER"
make -f makefile.win32 clean
make -f makefile.win32
mkdir -p $OUT
rm -rf $OUT/*
cp blobWarsAttrition.exe $OUT
cp -rL data $OUT
cp -rL gfx $OUT
cp -rL music $OUT
cp -rL sound $OUT
cp -rL manual $OUT
cp -rL locale $OUT
cp LICENSE $OUT
cp README.md $OUT
cp /usr/x86_64-w64-mingw32/bin/*.dll $OUT
cd $BUILDROOT
zip -r blobWarsAttrition-${VERSION}-${REVISION}.win32.zip $FOLDER
mv *.zip ../../dist
rm -rf $FOLDER

View File

@ -1,12 +1,12 @@
VERSION = 1.0
REVISION = 1
VERSION = 1.2
REVISION = 2
LOCALE_MO = $(patsubst %.po,%.mo,$(wildcard locale/*.po))
OUT = bin
SEARCHPATH += src
SEARCHPATH += src/combat
SEARCHPATH += src/entities
SEARCHPATH += src
SEARCHPATH += src/combat
SEARCHPATH += src/entities
SEARCHPATH += src/entities/blobs
SEARCHPATH += src/entities/boss
SEARCHPATH += src/entities/bullets
@ -23,8 +23,8 @@ SEARCHPATH += src/hub
SEARCHPATH += src/json
SEARCHPATH += src/system
SEARCHPATH += src/test
SEARCHPATH += src/util
SEARCHPATH += src/widgets
SEARCHPATH += src/util
SEARCHPATH += src/widgets
SEARCHPATH += src/world
vpath %.c $(SEARCHPATH)
@ -63,10 +63,13 @@ all: $(PROG) $(LOCALE_MO)
$(OUT)/%.o: %.c %.h $(DEPS)
@mkdir -p $(OUT)
$(CC) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
%.mo: %.po
ifneq ($(shell uname), AmigaOS)
msgfmt -c -o $@ $<
endif
# cleaning everything that can be automatically recreated with "make".
clean:
$(RM) $(OBJS) $(PROG) $(LOCALE_MO)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
gfx/hub/clouds.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

BIN
icons/blob.info Normal file

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 813 B

After

Width:  |  Height:  |  Size: 813 B

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Categories=Game;ActionGame;
Name=Blob Wars : Attrition
Comment=Mission and Objective based 2D Platform Game
Icon=blobwarsAttrition
Exec=blobwarsAttrition
Terminal=false
Type=Application

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Blob Wars : Attrition\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-15 12:32:17+0100\n"
"POT-Creation-Date: 2018-05-12 11:50:05+0100\n"
"PO-Revision-Date: ???\n"
"Last-Translator: ???\n"
"Language-Team: ???\n"
@ -64,6 +64,9 @@ msgstr ""
msgid "EyeDroid explosion kills"
msgstr ""
msgid "Best grenade combo"
msgstr ""
msgid "Time spent flying"
msgstr ""
@ -262,6 +265,18 @@ msgstr ""
msgid "Cells: %d / %d"
msgstr ""
msgid "Mission configuration"
msgstr ""
msgid "! Corrupt data"
msgstr ""
msgid "- empty -"
msgstr ""
msgid "Defeat enemies"
msgstr ""
msgid "This is an information point. Bob can stand by them for a few moments to see what they have to say. There are many scattered throughout this tutorial map, to help you learn how to play. They will also appear from time to time during the actual game. Stand by them for a short time, to get more information. If you get lost, tap the radar icon in the top left, to view a map of the local area."
msgstr ""
@ -349,9 +364,6 @@ msgstr ""
msgid "Defeat detachment leaders"
msgstr ""
msgid "Rescue POWs"
msgstr ""
msgid "Recover SD Card"
msgstr ""
@ -427,9 +439,6 @@ msgstr ""
msgid "Find Teeka"
msgstr ""
msgid "Defeat enemies"
msgstr ""
msgid "Destroy Toxic Barrels"
msgstr ""
@ -670,28 +679,28 @@ msgstr ""
msgid "Following the defeat of Galdov, Bob has organised his fellow Blobs into ridding the world of the remaining enemy forces. He will begin his mission at the beach front. This is a tutorial mission, that will allow you to become familiar with the gameplay and controls."
msgstr ""
msgid "Arriving at the beach front, Bob begins his search for the first detachment leader. Eliminating the leaders will cause the others to expose themselves, and allow Bob to work his way deeper into enemy territory. The enemy have also left some first aid kits in the area, which will help the war effort. He should collect those, and rescue any POWs in the area."
msgid "Arriving at the beach front, Bob begins his search for the first detachment leader. Eliminating the leaders will cause the others to expose themselves, and allow Bob to work his way deeper into enemy territory. The enemy have also left some first aid kits in the area, which will help the war effort. He should collect those, and rescue any MIAs in the area."
msgstr ""
msgid "A hard battle was fought on this beach, just some days ago. Not all of the Blobs made it back, however, and some have been taken as POWs. In addition to this, an SD card holding valuable intelligence data has been lost. Bob needs to find this SD card and free the POWs."
msgid "A hard battle was fought on this beach, just some days ago. Not all of the Blobs made it back, however, and need to be rescued. In addition to this, an SD card holding valuable intelligence data has been lost. Bob needs to find this SD card and rescue the MIAs."
msgstr ""
msgid "This part of the coastline was unsuccessfully defended by the Blobs, and the BioMechs moved in to claim it for their own. Bob's mission is simple: rescue the POWs and eliminate the detachment leader."
msgid "This part of the coastline was unsuccessfully defended by the Blobs, and the BioMechs moved in to claim it for their own. Bob's mission is simple: rescue the MIAs and eliminate the detachment leader."
msgstr ""
msgid "Some days ago, a group of Blobs set out to steal the blueprints for a BioMech super weapon. Many of the Blobs made it back to base, however, a handful did not. Both the Blobs and the parts of the blueprints that they were carrying need to be recovered."
msgstr ""
msgid "Teeka the Scout has managed to acquire a white keycard, to grant Bob access to one of the BioMech training grounds. Bob should meet Teeka, and get the keycard from him. He also needs to acquire more first aid, and rescue any POWs in the area."
msgid "Teeka the Scout has managed to acquire a white keycard, to grant Bob access to one of the BioMech training grounds. Bob should meet Teeka, and get the keycard from him. He also needs to acquire more first aid, and rescue any MIAs in the area."
msgstr ""
msgid "Like the grasslands, the greenlands are where the Blobs spend most of their time. This is also where most of the battles are fought. A transmitter has been lost in this area, which Bob must recover. He needs to also eliminate the detachment leader and sub leader, and rescue the POWs in the area."
msgid "Like the grasslands, the greenlands are where the Blobs spend most of their time. This is also where most of the battles are fought. A transmitter has been lost in this area, which Bob must recover. He needs to also eliminate the detachment leader and sub leader, and rescue the MIAs in the area."
msgstr ""
msgid "Alien invaders might have arrived, assimilated a number of a the Blobs around the planet, and a fierce war might still be in progress, but it's almost time for the Blobs' annual Cheese and Wine party. As well as his other duties, Bob must find some cheese to bring to the celebrations."
msgstr ""
msgid "Though the war effort is going well, moral in the Blobs forces needs to remain high if they are to win the war against the BioMechs. Unfortunately, the BioMechs have attacked the Blobs' vineyards, and taken some of the workers prisoner. Bob must therefore not only eliminate the detachment leaders and rescue the POWs, but also harvest the grapes himself."
msgid "Though the war effort is going well, moral in the Blobs forces needs to remain high if they are to win the war against the BioMechs. Unfortunately, the BioMechs have attacked the Blobs' vineyards, and taken some of the workers prisoner. Bob must therefore not only eliminate the detachment leaders and rescue the MIAs, but also harvest the grapes himself."
msgstr ""
msgid "The grape harvest went well, and much wine has been fortified as a result. However, the BioMechs have raided the wine stores and made off with a number of bottles. Bob sets out to get the wine back, before the BioMechs drink it all themselves."
@ -700,7 +709,7 @@ msgstr ""
msgid "Teeka has acquired a white keycard from the BioMechs, which will grant Bob access to one of their training and testing grounds. Bob needs to meet Teeka, to get the card from him. The BioMech detachment in the area has also been transporting recon data on 5 1/4 floppy disks. These need to be recovered, so that the Blobs can analyse it."
msgstr ""
msgid "The BioMechs have expanded their assault underground, using a series of tunnels to move their forces around undetected. There are no signs of any POWs, but Bob needs to eliminate as many of the BioMechs in the area as possible. The BioMechs have also dumped a number of toxic barrels here. That's not good for the environment ..."
msgid "The BioMechs have expanded their assault underground, using a series of tunnels to move their forces around undetected. There are no signs of any MIAs, but Bob needs to eliminate as many of the BioMechs in the area as possible. The BioMechs have also dumped a number of toxic barrels here. That's not good for the environment ..."
msgstr ""
msgid "The BioMechs have set up a number of sentry cannons in these tunnels, in an attempt to secure them. Bob needs to destroy these cannons, and make his way to the exit. There are also a handful of toxic barrels here, that need to be destroyed."
@ -715,19 +724,19 @@ msgstr ""
msgid "Teeka has signalled that he has managed to acquire another white keycard from the enemy. Bob should retrieve it from him, as soon as possible. The scout has also warned Bob that the BioMechs have attempted to lock this area down tight, without a keycard in sight. Bob should consider only starting this mission with a good stock of cards."
msgstr ""
msgid "One of the five enemy outposts that has been identified. Bob will have to get in there and plant some bombs, to bring the place down. Find the bombs and set them onto the designation bomb spots. There are thought to be some POWs in the outpost, too, so they will need to be rescued. Exercise caution: the enemies within the outpost are reportedly more powerful than their cousins littered throughout the field."
msgid "One of the five enemy outposts that has been identified. Bob will have to get in there and plant some bombs, to bring the place down. Find the bombs and set them onto the designation bomb spots. There are thought to be some MIAs in the outpost, too, taken as prison. They will need to be rescued. Exercise caution: the enemies within the outpost are reportedly more powerful than their cousins littered throughout the field."
msgstr ""
msgid "Another of the 5 outposts. As with the others, Bob will have to get in here and set some explosives. There are some POWs in here that will need rescuing, too. As with all the other outposts, caution should be taken, as the enemies here are more powerful than those out in the field."
msgid "Another of the 5 outposts. As with the others, Bob will have to get in here and set some explosives. There are some MIAs in here that will need rescuing, too. As with all the other outposts, caution should be taken, as the enemies here are more powerful than those out in the field."
msgstr ""
msgid "The 3rd outpost! Get in there and plant some bombs, to bring the place down. And don't forget to rescue any POWs that might be locked up. Expect heavier resistance compared to the outposts that have preceded this one."
msgid "The 3rd outpost! Get in there and plant some bombs, to bring the place down. And don't forget to rescue any MIAs that might be locked up. Expect heavier resistance compared to the outposts that have preceded this one."
msgstr ""
msgid "Outpost number 4! Bob's mission is simple: get in there, plant the explosives, rescue the POWs, and get the hell out! Nothing much to see here. And once the bombs go off, even less!"
msgid "Outpost number 4! Bob's mission is simple: get in there, plant the explosives, rescue the MIAs, and get the hell out! Nothing much to see here. And once the bombs go off, even less!"
msgstr ""
msgid "Problem. This outpost is stuffed full of POWs. Taking it down might not be such a good idea. Bob will instead have to go in there and rescue all the prisoners, and come back later to plant the bombs. Teeka has already infiltrated the outpost and is reporting that there are well over two dozen POWs here. Best get cracking."
msgid "Problem. This outpost is stuffed full of MIAs. Taking it down might not be such a good idea. Bob will instead have to go in there and rescue all the prisoners, and come back later to plant the bombs. Teeka has already infiltrated the outpost and is reporting that there are well over two dozen MIAs here. Best get cracking."
msgstr ""
msgid "This is one of the proving grounds that the BioMechs have been using to develop new troops. A white keycard is required to gain access. Anything could lie beyond. Bob should proceed with caution."

View File

@ -19,10 +19,15 @@ _OBJS += unixInit.o
include common.mk
NPROCS = $(shell grep -c 'processor' /proc/cpuinfo)
MAKEFLAGS += -j$(NPROCS)
CXXFLAGS += `sdl2-config --cflags` -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\"
CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
CXXFLAGS += -g -lefence
CXXFLAGS += -fms-extensions -std=gnu11
ifneq ("$(wildcard .errors)","")
CXXFLAGS += -Wall -Wempty-body -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
endif
LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm -lz -lpng
@ -53,13 +58,13 @@ install:
cp -p icons/$(PROG)-128x128.png $(INST_ICON_DIR)/128x128/apps/$(PROG).png
mkdir -p $(INST_DESKTOP_DIR)
cp -p icons/$(PROG).desktop $(INST_DESKTOP_DIR)
@for f in $(LOCALE_MO); do \
lang=`echo $$f | sed -e 's/^locale\///;s/\.mo$$//'`; \
mkdir -p $(INST_LOCALE_DIR)/$$lang/LC_MESSAGES; \
cp -v $$f $(INST_LOCALE_DIR)/$$lang/LC_MESSAGES/$(PROG).mo; \
done
uninstall:
$(RM) $(BIN_DIR)/$(PROG)
$(RM) -rf $(DATA_DIR)
@ -68,7 +73,7 @@ uninstall:
$(RM) $(ICON_DIR)/64x64/apps/$(PROG).png
$(RM) $(ICON_DIR)/128x128/apps/$(PROG).png
$(RM) $(DESKTOP_DIR)/$(PROG).desktop
@for f in $(LOCALE_MO); do \
lang=`echo $$f | sed -e 's/^locale\///;s/\.mo$$//'`; \
$(RM) -v $(LOCALE_DIR)/$$lang/LC_MESSAGES/$(PROG).mo; \
@ -79,20 +84,20 @@ dist:
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
mkdir $(PROG)-$(VERSION).$(REVISION)
cp -rL $(DIST_FILES) $(PROG)-$(VERSION).$(REVISION)
tar czf $(PROG)-$(VERSION)-$(REVISION).linux-x86.tar.gz $(PROG)-$(VERSION).$(REVISION)
tar czf $(PROG)-$(VERSION).$(REVISION).linux-x86.tar.gz $(PROG)-$(VERSION).$(REVISION)
mkdir -p dist
mv $(PROG)-$(VERSION)-$(REVISION).linux-x86.tar.gz dist
mv $(PROG)-$(VERSION).$(REVISION).linux-x86.tar.gz dist
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
# prepare an archive for the program
src-dist:
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
mkdir $(PROG)-$(VERSION).$(REVISION)
cp -rL $(SRC_DIST_FILES) $(PROG)-$(VERSION).$(REVISION)
git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --date=short >$(PROG)-$(VERSION).$(REVISION)/CHANGELOG.raw
tar czf $(PROG)-$(VERSION)-$(REVISION).src.tar.gz $(PROG)-$(VERSION).$(REVISION)
tar czf $(PROG)-$(VERSION).$(REVISION).src.tar.gz $(PROG)-$(VERSION).$(REVISION)
mkdir -p dist
mv $(PROG)-$(VERSION)-$(REVISION).src.tar.gz dist
mv $(PROG)-$(VERSION).$(REVISION).src.tar.gz dist
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
.PHONY: dist

65
makefile.mos Normal file
View File

@ -0,0 +1,65 @@
PROG = blobwarsAttrition
CC = gcc
PREFIX ?= /usr
BIN_DIR ?= $(PREFIX)/bin
DATA_DIR ?= data
LOCALE_DIR = locale
ICON_DIR = $(PREFIX)/share/icons/hicolor
DESKTOP_DIR = $(PREFIX)/share/applications
DESTDIR ?=
INST_BIN_DIR = $(DESTDIR)$(BIN_DIR)
INST_DATA_DIR = $(DESTDIR)$(DATA_DIR)
INST_LOCALE_DIR = $(DESTDIR)$(LOCALE_DIR)
INST_ICON_DIR = $(DESTDIR)$(ICON_DIR)
INST_DESKTOP_DIR = $(DESTDIR)$(DESKTOP_DIR)
SEARCHPATH += src/plat/mos
_OBJS += mosInit.o
include common.mk
CXXFLAGS += -O3 -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\" -D__USE_INLINE__
CXXFLAGS += -I/sdk/gg/usr/local/include -g -lefence
CXXFLAGS += -fms-extensions -std=gnu11 -noixemul
ifneq ("$(wildcard .errors)","")
CXXFLAGS += -Wall -Wempty-body -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
endif
LDFLAGS += -noixemul -lSDL2_image -lSDL2_ttf -lfreetype -ltiff -lpng16 -ljpeg -lz -lm
LDFLAGS += -lSDL2_mixer -lmikmod -lmodplug -lFLAC -lvorbisfile -lvorbis -logg
LDFLAGS += -lSDL2 -lstdc++
SHARED_FILES = LICENSE README.md data gfx manual music sound icons
DIST_FILES = $(SHARED_FILES) locale $(PROG)
SRC_DIST_FILES = $(SHARED_FILES) src makefile* common.mk
# linking the program.
$(PROG): $(OBJS)
$(CC) -o $@ $(OBJS) $(LDFLAGS)
# prepare an archive for the program
dist:
mkdir -p release/$(PROG)-$(VERSION).$(REVISION)
cp $(PROG) release/$(PROG)-$(VERSION).$(REVISION)/
strip release/$(PROG)-$(VERSION).$(REVISION)/$(PROG)
cp icons/blob.info release/$(PROG)-$(VERSION).$(REVISION)/$(PROG).info
cp LICENSE release/$(PROG)-$(VERSION).$(REVISION)/
cp README.md release/$(PROG)-$(VERSION).$(REVISION)/
cp README-Amiga.md release/$(PROG)-$(VERSION).$(REVISION)/
lha -aeqr3 a $(PROG)-MOS-$(VERSION).$(REVISION).lha release/
# prepare an archive for the program
src-dist:
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
mkdir $(PROG)-$(VERSION).$(REVISION)
cp -rL $(SRC_DIST_FILES) $(PROG)-$(VERSION).$(REVISION)
git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --date=short >$(PROG)-$(VERSION).$(REVISION)/CHANGELOG.raw
tar czf $(PROG)-$(VERSION).$(REVISION).src.tar.gz $(PROG)-$(VERSION).$(REVISION)
mkdir -p dist
mv $(PROG)-$(VERSION).$(REVISION).src.tar.gz dist
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
.PHONY: dist

65
makefile.os4 Normal file
View File

@ -0,0 +1,65 @@
PROG = blobwarsAttrition
CC = gcc
PREFIX ?= /usr
BIN_DIR ?= $(PREFIX)/bin
DATA_DIR ?= data
LOCALE_DIR = locale
ICON_DIR = $(PREFIX)/share/icons/hicolor
DESKTOP_DIR = $(PREFIX)/share/applications
DESTDIR ?=
INST_BIN_DIR = $(DESTDIR)$(BIN_DIR)
INST_DATA_DIR = $(DESTDIR)$(DATA_DIR)
INST_LOCALE_DIR = $(DESTDIR)$(LOCALE_DIR)
INST_ICON_DIR = $(DESTDIR)$(ICON_DIR)
INST_DESKTOP_DIR = $(DESTDIR)$(DESKTOP_DIR)
SEARCHPATH += src/plat/os4
_OBJS += os4Init.o
include common.mk
CXXFLAGS += -O3 -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\" -D__USE_INLINE__
CXXFLAGS += -g -lefence
CXXFLAGS += -fms-extensions -std=gnu11
ifneq ("$(wildcard .errors)","")
CXXFLAGS += -Wall -Wempty-body -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
endif
LDFLAGS += -lauto -lSDL2_image -lSDL2_ttf -lfreetype -ltiff -lwebp -lpng -ljpeg -lz -lm
LDFLAGS += -lSDL2_mixer -lmikmod -lmodplug -lFLAC -lsmpeg2 -lvorbisfile -lvorbis -logg
LDFLAGS += -lSDL2 -lpthread -athread=native -lstdc++
SHARED_FILES = LICENSE README.md data gfx manual music sound icons
DIST_FILES = $(SHARED_FILES) locale $(PROG)
SRC_DIST_FILES = $(SHARED_FILES) src makefile* common.mk
# linking the program.
$(PROG): $(OBJS)
$(CC) -o $@ $(OBJS) $(LDFLAGS)
# prepare an archive for the program
dist:
mkdir -p release/$(PROG)-$(VERSION).$(REVISION)
cp $(PROG) release/$(PROG)-$(VERSION).$(REVISION)/
strip release/$(PROG)-$(VERSION).$(REVISION)/$(PROG)
cp icons/blob.info release/$(PROG)-$(VERSION).$(REVISION)/$(PROG).info
cp LICENSE release/$(PROG)-$(VERSION).$(REVISION)/
cp README.md release/$(PROG)-$(VERSION).$(REVISION)/
cp README-Amiga.md release/$(PROG)-$(VERSION).$(REVISION)/
lha -aeqr3 a $(PROG)-OS4-$(VERSION).$(REVISION).lha release/
# prepare an archive for the program
src-dist:
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
mkdir $(PROG)-$(VERSION).$(REVISION)
cp -rL $(SRC_DIST_FILES) $(PROG)-$(VERSION).$(REVISION)
git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --date=short >$(PROG)-$(VERSION).$(REVISION)/CHANGELOG.raw
tar czf $(PROG)-$(VERSION).$(REVISION).src.tar.gz $(PROG)-$(VERSION).$(REVISION)
mkdir -p dist
mv $(PROG)-$(VERSION).$(REVISION).src.tar.gz dist
$(RM) -rf $(PROG)-$(VERSION).$(REVISION)
.PHONY: dist

View File

@ -1,7 +1,6 @@
PROG = blobWarsAttrition.exe
PROG = blobwarsAttrition.exe
CC = x86_64-w64-mingw32-gcc
SDLC = /usr/x86_64-w64-mingw32/bin/sdl2-config
LIBPATH = /usr/x86_64-w64-mingw32/lib
LOCALE_DIR = locale
SEARCHPATH += src/plat/win32
@ -9,6 +8,9 @@ _OBJS += win32Init.o
include common.mk
NPROCS = $(shell grep -c 'processor' /proc/cpuinfo)
MAKEFLAGS += -j$(NPROCS)
CXXFLAGS += `$(SDLC) --cflags` -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\"
CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
CXXFLAGS += -g -lefence

BIN
manual/gamePlus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -11,7 +11,7 @@
<img src="title.png" /><br />
Gameplay Manual<br />
</p>
<p style="font-size: 14px">Last updated: 2nd April 2018</p>
<p style="font-size: 14px">Last updated: 18th May 2018</p>
</div>
<div>
@ -31,7 +31,7 @@ Blob Wars : Attrition is a mission and objective-based 2D platformer. It is the
<p>
To quickly start playing the game:
<ul>
<li>Run the Blob Wars executable (./blobWarsAttrition on Linux, blobWarsAttrition.exe) on Windows).</li>
<li>Run the Blob Wars executable (./blobwarsAttrition on Linux, blobwarsAttrition.exe) on Windows).</li>
<li>Choose New Game and select a save slot.</li>
<li>On the world map screen, use the mouse or keyboard control to select the Beach Approach tutorial mission.</li>
<li>Play and complete the training mission to proceed with the game (or quit the mission to proceed more quickly).</li>
@ -241,8 +241,18 @@ Pressing the Radar key (Tab by default) during a mission will bring up the radar
<p>
If Bob loses all his health, the mission is failed. At this point, you will have the option to restart the mission or return to the hub. Restarting the mission will reset everything to the way it was when the mission began; keys, items, etc. will be reset to their previous state, including the player's inventory and health bonuses. In the case of a new mission, this will mean restarting from the beginning. If returning to the mission, the player will restart from that point.
</p>
<h4>Post Game</h4>
<p>
Once all missions have been completed, the player will have the option to continue the game in Free Play mode. They may play any mission they like, at any time. The state of the mission will not be saved, however.
<img src="gamePlus.jpg" class="screenshot" />
Once all missions have been completed, the player will have the option to continue the game in Free Play mode. They may play any mission they like, at any time. The state of the mission will not be saved, however. A number of additional gameplay options will also become available.
<ul>
<li><span class='highlight'>No Doors</span>: Removes all doors from the mission (keys will remain).</li>
<li><span class='highlight'>Random Enemies</span>: Enemies will have random weapons, leading to slightly harder gameplay.</li>
<li><span class='highlight'>Tougher Enemies</span>: Enemies will require more hits to take them down.</li>
<li><span class='highlight'>Defeat All Enemies</span>: All enemies will need to be defeated in order to finish the mission. No new enemies will spawn.</li>
<li><span class='highlight'>Mirror World</span>: The layout of the level will be horizontally mirrored, with enemy placements, items, doors, structures, etc. all appearing in opposite way around.</li>
</ul>
</p>
<h3>Options</h3>
@ -258,7 +268,6 @@ The options screen can be access at most times during the game. It allow you to
<li><span class='highlight'>Sound Volume</span>: change the volume of the sound effect. Use the left and right controls to change the levels.</li>
<li><span class='highlight'>Music Volume</span>: change the volume of the music. Use the left and right controls to change the levels.</li>
<li><span class='highlight'>Blood</span>: whether or not to show blood. When blood is off, enemy blobs won't scream when they die and will also disappear in a puff of white when they are defeated. Blood will not splatter the ground. The Extra option will do the opposite and leave more blood around for longer (this might clutter the screen a little, so be careful with this option).</li>
<li><span class='highlight'>Trophy Screenshot</span>: whether or not to save a screenshot when a trophy is earned. The screenshot is saved to the same location as the save files. Be aware that this might cause the game to pause for a moment when the screenshot to saved.</li>
<li><span class='highlight'>Trophy Alert</span>: whether or not to show an in-game alert when a trophy is earned. Switching to to Restricted will mean that alerts are not shown during a mission. This option may be best if you find the alerts obscuring gameplay.</li>
<li><span class='highlight'>Hud Inventory</span>: whether to show the in-game inventory in the top right corner of the screen during a mission. Turn this off if you find it either distract or is obscuring the gameplay.</li>
<li><span class='highlight'>Controls</span>: go to the controls configuration screen. See below for more details.</li>
@ -286,7 +295,7 @@ To change a control, highlight the relevant options and press Return or Space, t
<h3>Misc. Game Info</h3>
<p>
Blob Wars : Attrition features an in-game trophy system, not unlike the achievement and trophy system found in Steam, Xbox Live, and PSN. This is entirely an offline system and exists purely for fun. Trophies are awarded for things such as completing missions, defeating a certain number of enemies, and rescuing MIAs. You can view the trophies you have earned and those that are outstanding in the hub and mission menus. When a trophy is earned, a notification will appear on the screen. If you find these distracting, you can switch them off in the options screen (or set them to be restricted, so that they do not appear during missions). A screenshot is also saved, which can also be turned off.
Blob Wars : Attrition features an in-game trophy system, not unlike the achievement and trophy system found in Steam, Xbox Live, and PSN. This is entirely an offline system and exists purely for fun. Trophies are awarded for things such as completing missions, defeating a certain number of enemies, and rescuing MIAs. You can view the trophies you have earned and those that are outstanding in the hub and mission menus. When a trophy is earned, a notification will appear on the screen. If you find these distracting, you can switch them off in the options screen (or set them to be restricted, so that they do not appear during missions).
</p>
<h3>License</h3>
@ -299,7 +308,7 @@ Please refer to the LICENSE and README.md files that came with this game for inf
Blob Wars : Attrition is a port of the Android game of the same name. It is the third game in the Blob Wars series of games, that began in 2002.
</p>
<p>
<a href="http://www.stephenjsweeney.com/games/attrition">http://www.stephenjsweeney.com/games/attrition</a>
<a href="http://www.parallelrealities.co.uk/games/attrition">http://www.parallelrealities.co.uk/games/attrition</a>
</p>
</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -7,5 +7,5 @@ table {border-collapse: collapse;}
table, th, td {border: 1px solid white; padding: 8px;}
span.highlight {color: #fb0; font-weight: bold;}
img.screenshot {width: 800px; padding: 2px; border: 1px solid #ccc; margin-left: auto; margin-right: auto; display: block;}
div.annotation {font-size: 12px; position: absolute; background-color: #08f; color: #fff; padding: 5px; font-weight: bold; border: 1px #fff solid; text-align: center}
div.annotation {border-radius: 50%; font-size: 12px; position: absolute; background-color: #08f; color: #fff; padding: 5px; font-weight: bold; border: 1px #adf solid; text-align: center; width: 21px; height: 21px;}
div.annotationContainer {position: relative; width: 800px; display: block; margin-left: auto; margin-right: auto;}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -26,37 +26,37 @@ int hasLineOfSight(Entity *src, Entity *dest)
float sx, sy, tx, ty, dx, dy;
Entity **candidates, *e;
SDL_Rect losBounds;
sx = src->x + (src->w / 2);
sy = src->y + (src->h / 2);
tx = dest->x + (dest->w / 2);
ty = dest->y + (dest->h / 2);
losBounds.x = (int) MIN(src->x, dest->x);
losBounds.y = (int) MIN(src->y, dest->y);
losBounds.w = (int) (MAX(src->x, dest->x) - losBounds.x);
losBounds.h = (int) (MAX(src->y, dest->y) - losBounds.y);
candidates = getAllEntsWithin(losBounds.x, losBounds.y, losBounds.w, losBounds.h, NULL);
getSlope(sx, sy, tx, ty, &dx, &dy);
dx *= 8;
dy *= 8;
while (1)
{
sx -= dx;
sy -= dy;
mx = sx / MAP_TILE_SIZE;
my = sy / MAP_TILE_SIZE;
if (isSolid(mx, my))
{
return 0;
}
for (i = 0, e = candidates[i] ; e != NULL ; e = candidates[++i])
{
if (e != src && collision(sx, sy, 8, 8, e->x, e->y, e->w, e->h))
@ -65,7 +65,7 @@ int hasLineOfSight(Entity *src, Entity *dest)
{
return 0;
}
if (e == dest)
{
return 1;
@ -73,7 +73,7 @@ int hasLineOfSight(Entity *src, Entity *dest)
}
}
}
return 0;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -29,7 +29,7 @@ void addExplosion(float x, float y, int radius, Entity *owner)
Entity **candidates, *e;
float power;
int i;
playBattleSound(SND_EXPLOSION, 0, x, y);
/* assuming x and y were from the top left of the entity */
@ -42,7 +42,7 @@ void addExplosion(float x, float y, int radius, Entity *owner)
radiusRect.y = (int) (y - radius);
radiusRect.w = radius * 2;
radiusRect.h = radius * 2;
if (killTimer < SDL_GetTicks())
{
numKilled = 0;
@ -77,17 +77,17 @@ void addExplosion(float x, float y, int radius, Entity *owner)
{
stunBob();
}
if (owner->type == ET_ENEMY && e->health <= 0 && e->type == ET_ENEMY && strstr(((Unit*)owner)->unitType, "EyeDroid"))
{
game.stats[STAT_EYE_DROID_EXPLOSION_KILLS]++;
}
if (e->health <= 0)
{
e->dx = rrnd(-radius / 8, radius / 8);
e->dy = rrnd(-5, 0);
if (owner->type == ET_BOB)
{
numKilled++;
@ -98,9 +98,16 @@ void addExplosion(float x, float y, int radius, Entity *owner)
}
}
}
if (numKilled >= 12)
if (numKilled >= 2)
{
awardTrophy("GRENADE_COMBO");
setGameplayMessage(MSG_STANDARD, "%d hit grenade combo!", numKilled);
game.stats[STAT_GRENADE_COMBO] = MAX(game.stats[STAT_GRENADE_COMBO], numKilled);
if (numKilled >= 12)
{
awardTrophy("GRENADE_COMBO");
}
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -26,6 +26,7 @@ extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore);
extern int getDistance(int x1, int y1, int x2, int y2);
extern void playBattleSound(int snd, int ch, int x, int y);
extern int rrnd(int low, int high);
extern void setGameplayMessage(int newMessageType, const char *format, ...);
extern void stunBob(void);
extern void swapSelf(Entity *e);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -56,7 +56,7 @@ void initWeapons(void)
missileSprite[0] = getSprite("MissileRight");
missileSprite[1] = getSprite("MissileLeft");
weaponName[WPN_PISTOL] = _("Pistol");
weaponName[WPN_PLASMA] = _("Plasma Rifle");
weaponName[WPN_SPREAD] = _("Spread Gun");
@ -68,10 +68,10 @@ void initWeapons(void)
void firePistol(void)
{
Bullet *bullet;
if (world.bob->facing != FACING_DIE)
{
bullet = createBaseBullet((Unit*)world.bob);
bullet = createBaseBullet((Unit*)world.bob, bulletSprite[0]->frames[0]->rect.w);
bullet->weaponType = WPN_PISTOL;
bullet->facing = world.bob->facing;
bullet->sprite[0] = bulletSprite[0];
@ -88,7 +88,7 @@ void fireAimedShot(Unit *owner)
int x, y;
float dx, dy;
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
x = (int) (world.bob->x + rrnd(-8, 24));
@ -96,7 +96,7 @@ void fireAimedShot(Unit *owner)
getSlope(x, y, owner->x, owner->y, &dx, &dy);
bullet = createBaseBullet(owner);
bullet = createBaseBullet(owner, aimedSprite->w);
bullet->weaponType = WPN_AIMED_PISTOL;
bullet->dx = dx * 6;
bullet->dy = dy * 6;
@ -112,10 +112,10 @@ void fireAimedShot(Unit *owner)
void fireMachineGun(Unit *owner)
{
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
bullet = createBaseBullet(owner);
bullet = createBaseBullet(owner, bulletSprite[0]->w);
bullet->weaponType = WPN_MACHINE_GUN;
bullet->sprite[0] = bulletSprite[0];
bullet->sprite[1] = bulletSprite[1];
@ -128,10 +128,10 @@ void fireMachineGun(Unit *owner)
void firePlasma(Unit *owner)
{
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
bullet = createBaseBullet(owner);
bullet = createBaseBullet(owner, plasmaSprite[0]->w);
bullet->weaponType = WPN_PLASMA;
bullet->sprite[0] = plasmaSprite[0];
bullet->sprite[1] = plasmaSprite[1];
@ -155,7 +155,7 @@ void fireSpread(Unit *owner, int numberOfShots)
for (i = 0 ; i < numberOfShots ; i++)
{
bullet = createBaseBullet(owner);
bullet = createBaseBullet(owner, spreadShotSprite->w);
bullet->weaponType = WPN_SPREAD;
bullet->sprite[0] = bullet->sprite[1] = owner->type == ET_BOB ? spreadShotSprite : alienSpreadShotSprite;
bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15;
@ -173,12 +173,10 @@ void fireSpread(Unit *owner, int numberOfShots)
void fireLaser(Unit *owner)
{
Bullet *laser;
if (owner->facing != FACING_DIE)
{
laser = createBaseBullet(owner);
laser->x = owner->x + owner->w / 2;
laser->y = owner->y + owner->h / 2;
laser = createBaseBullet(owner, laserSprite[0]->w);
laser->facing = owner->facing;
laser->dx = owner->facing == FACING_RIGHT ? 20 : -20;
laser->health = FPS * 3;
@ -195,11 +193,10 @@ void fireLaser(Unit *owner)
void fireGrenade(Unit *owner)
{
Bullet *grenade;
if (owner->facing != FACING_DIE)
{
grenade = createBaseBullet(owner);
grenade->x = owner->x + owner->w / 2;
grenade = createBaseBullet(owner, grenadeSprite->w);
grenade->y = owner->y;
grenade->facing = owner->facing;
grenade->health = FPS * 3;
@ -220,14 +217,14 @@ void fireShotgun(Unit *owner)
int i;
float dx, dy;
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
for (i = 0 ; i < 8 ; i++)
{
getSlope(world.bob->x + rrnd(0, 40), world.bob->y + rrnd(0, 40), owner->x, owner->y, &dx, &dy);
bullet = createBaseBullet(owner);
bullet = createBaseBullet(owner, 0);
bullet->weaponType = WPN_SHOTGUN;
bullet->x = owner->x + (owner->w / 2) + rrnd(-8, 8);
bullet->y = owner->y + (owner->h / 2) + rrnd(-8, 8);
@ -246,11 +243,10 @@ void fireShotgun(Unit *owner)
void fireMissile(Unit *owner)
{
Bullet *missile;
if (owner->facing != FACING_DIE)
{
missile = createBaseBullet(owner);
missile->x = owner->x + owner->w / 2;
missile = createBaseBullet(owner, missileSprite[0]->w);
missile->y = owner->y + 10;
missile->facing = owner->facing;
missile->dx = owner->facing == FACING_RIGHT ? 10 : -10;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../common.h"
extern Bullet *createBaseBullet(Unit *owner);
extern Bullet *createBaseBullet(Unit *owner, int bulletWidth);
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);
extern Sprite *getSprite(char *name);
extern void initGrenade(Bullet *b);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -39,6 +39,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define SAVE_FILENAME "game.save"
#define CONFIG_FILENAME "config.json"
#define UI_WIDTH 1280
#define UI_HEIGHT 720
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
@ -50,13 +53,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_FONTS 64
#define NUM_TEXT_BUCKETS 64
#define TEXT_TTL (1000 * 20)
#define NUM_GLYPH_BUCKETS 128
#define MAX_NAME_LENGTH 32
#define MAX_DESCRIPTION_LENGTH 512
#define MAX_LINE_LENGTH 1024
#define MAX_FILENAME_LENGTH 1024
#define MAX_PATH_LENGTH 4096
#define NUM_TEXTURE_BUCKETS 32
#define NUM_ATLAS_BUCKETS 64
@ -64,9 +66,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAP_WIDTH 200
#define MAP_HEIGHT 200
#define MAP_RENDER_WIDTH ((SCREEN_WIDTH / MAP_TILE_SIZE) + 1)
#define MAP_RENDER_HEIGHT ((SCREEN_HEIGHT / MAP_TILE_SIZE) + 1)
#define MAP_TILE_SIZE 64
#define MAP_TILE_AIR 0
#define MAP_TILE_WATER 1
@ -80,6 +79,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAP_TILE_OUTSIDE 255
#define MAP_TILE_MAX 256
/* for mirroring */
#define MAP_PIXEL_WIDTH (MAP_WIDTH * MAP_TILE_SIZE)
#define JUMP_POWER -12
#define MAX_OXYGEN (FPS * 10)
#define MAX_KEY_TYPES 8
@ -145,6 +147,7 @@ enum
#define EF_NO_OBSERVE (2 << 18)
#define EF_BULLET_HIT (2 << 19)
#define EF_CRUSHABLE (2 << 20)
#define EF_MIRROR (2 << 21)
#define GRAVITY_POWER 0.5f
#define FRICTION 0.75f
@ -358,6 +361,7 @@ enum
STAT_SHOTS_HIT,
STAT_SHOT_ACCURACY,
STAT_EYE_DROID_EXPLOSION_KILLS,
STAT_GRENADE_COMBO,
STAT_FLY_TIME,
STAT_SWIM_TIME,
STAT_CHERRIES_PICKED_UP,
@ -429,5 +433,15 @@ enum
ST_HUB_KEYS,
ST_HUB_HEARTS,
ST_HUB_CELLS,
ST_CORRUPT_SAVE,
ST_EMPTY_SAVE,
ST_MISSION_CONFIG,
ST_MAX
};
#define PLUS_NONE 0
#define PLUS_NO_DOORS (2 << 0)
#define PLUS_STRONGER (2 << 1)
#define PLUS_RANDOM (2 << 2)
#define PLUS_KILL_ALL (2 << 3)
#define PLUS_MIRROR (2 << 4)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -54,12 +54,12 @@ static int oldFacing;
Entity *initBob(void)
{
Bob *b;
b = malloc(sizeof(Bob));
memset(b, 0, sizeof(Bob));
initEntity((Entity*)b);
STRNCPY(b->name, "Bob", MAX_NAME_LENGTH);
b->type = ET_BOB;
@ -83,9 +83,9 @@ Entity *initBob(void)
b->reload = 0;
b->flags |= EF_SWIMS | EF_BOMB_SHIELD;
superAnimate = b->animate;
b->tick = tick;
b->init = init;
b->applyDamage = applyDamage;
@ -96,21 +96,21 @@ Entity *initBob(void)
b->die = die;
b->load = load;
b->save = save;
checkpointTimer = 0;
oldFacing = b->facing;
return (Entity*)b;
}
static void init(void)
{
changeSprite(walkSprite);
world.bob->checkpoints[0].x = world.bob->x;
world.bob->checkpoints[0].y = world.bob->y;
superAnimate();
}
@ -243,7 +243,7 @@ static void handeImmunity(void)
world.bob->checkpoints[i].x = world.bob->checkpoints[i - 1].x;
world.bob->checkpoints[i].y = world.bob->checkpoints[i - 1].y;
}
world.bob->checkpoints[0].x = world.bob->x;
world.bob->checkpoints[0].y = world.bob->y;
checkpointTimer = FPS;
@ -361,11 +361,11 @@ static void doBobInWater(void)
static void doDying(void)
{
int mx, my;
if (--world.bob->health <= -(FPS * 2))
{
world.bob->flags |= EF_GONE;
if (app.config.blood)
{
throwFleshChunks(world.bob->x + world.bob->w / 2, world.bob->y + world.bob->h / 2, rrnd(3, 6));
@ -385,7 +385,7 @@ static void doDying(void)
{
playSound(SND_POP, world.bob->uniqueId % MAX_SND_CHANNELS);
}
mx = (int) ((world.bob->x + (world.bob->w / 2)) / MAP_TILE_SIZE);
my = (int) (world.bob->y / MAP_TILE_SIZE) + 1;
addBloodDecal(mx, my);
@ -472,7 +472,7 @@ static void bobWalk(void)
{
fireWeapon();
}
if (isControl(CONTROL_JETPACK))
{
activate(1);
@ -511,7 +511,7 @@ static void bobSwim(void)
{
firePistol();
}
if (isControl(CONTROL_JETPACK))
{
activate(1);
@ -549,7 +549,7 @@ static void bobFly(void)
{
fireWeapon();
}
if (isControl(CONTROL_JETPACK))
{
activate(1);
@ -618,7 +618,7 @@ void resetAtCheckpoint(void)
{
world.bob->x = world.bob->checkpoints[0].x;
world.bob->y = world.bob->checkpoints[0].y;
world.bob->facing = oldFacing;
world.bob->outTimer = 0;
world.bob->flags |= EF_FLICKER;
@ -666,7 +666,7 @@ static void die(void)
static SDL_Rect *getCurrentSprite(void)
{
Sprite *s;
s = (world.bob->alive == ALIVE_ALIVE && world.bob->stunTimer <= 0) ? world.bob->sprite[world.bob->facing] : world.bob->sprite[FACING_DIE];
{
return &world.bob->sprite[world.bob->facing]->frames[world.bob->spriteFrame]->rect;
@ -677,7 +677,7 @@ static SDL_Rect *getCurrentSprite(void)
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "WARNING: %s (%d) bad sprite frames - %d > %d\n", world.bob->name, world.bob->type, world.bob->spriteFrame, s->numFrames);
world.bob->spriteFrame = 0;
}
return &s->frames[world.bob->spriteFrame]->rect;
}
@ -689,9 +689,9 @@ static void animate(void)
{
oldFacing = world.bob->facing;
}
world.bob->facing = FACING_DIE;
superAnimate();
}
else if (world.bob->dx != 0 || world.bob->flags & EF_WEIGHTLESS)
@ -705,10 +705,21 @@ static void load(cJSON *root)
world.bob->x = cJSON_GetObjectItem(root, "x")->valueint;
world.bob->y = cJSON_GetObjectItem(root, "y")->valueint;
world.bob->facing = lookup(cJSON_GetObjectItem(root, "facing")->valuestring);
if (game.plus & PLUS_MIRROR)
{
world.bob->x = MAP_PIXEL_WIDTH - world.bob->x;
}
}
static void save(cJSON *root)
{
/* in case Bob was put into stun state during save */
if (world.bob->facing == FACING_DIE)
{
world.bob->facing = oldFacing;
}
cJSON_AddStringToObject(root, "type", "Bob");
cJSON_AddNumberToObject(root, "x", world.bob->checkpoints[0].x);
cJSON_AddNumberToObject(root, "y", world.bob->checkpoints[0].y);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -32,14 +32,14 @@ static void save(cJSON *root);
Entity *initMIA(void)
{
MIA *m;
m = malloc(sizeof(MIA));
memset(m, 0, sizeof(MIA));
initEntity((Entity*)m);
m->type = ET_MIA;
m->tx = m->ty = -1;
m->sprite[FACING_LEFT] = getSprite("MIA");
@ -60,7 +60,7 @@ Entity *initMIA(void)
m->save = save;
m->isMissionTarget = 1;
return (Entity*)m;
}
@ -81,9 +81,9 @@ static void reset(void)
static void tick(void)
{
MIA *m;
m = (MIA*)self;
if (--m->shudderTimer <= 0)
{
m->x = (m->tx + rand() % 4);
@ -97,7 +97,7 @@ static void tick(void)
addMIATeleportStars(m->x + rand() % m->w, m->y + rand() % m->h);
m->starTimer = 1;
}
world.saveDelay = FPS;
}
}
@ -105,9 +105,9 @@ static void tick(void)
static void touch(Entity *other)
{
MIA *m;
m = (MIA*)self;
if (m->isMissionTarget && other == (Entity*)world.bob)
{
m->action = preTeleport;
@ -125,49 +125,49 @@ static void touch(Entity *other)
static void preTeleport(void)
{
MIA *m;
m = (MIA*)self;
if (--m->teleportTimer <= FPS)
{
m->action = teleport;
m->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
m->dy = -5;
}
world.saveDelay = FPS;
}
static void teleport(void)
{
MIA *m;
m = (MIA*)self;
if (--m->teleportTimer <= 0)
{
addTeleportStars(self);
m->alive = ALIVE_DEAD;
}
world.saveDelay = FPS;
}
static void load(cJSON *root)
{
MIA *m;
m = (MIA*)self;
m->active = cJSON_GetObjectItem(root, "isMissionTarget")->valueint;
}
static void save(cJSON *root)
{
MIA *m;
m = (MIA*)self;
cJSON_AddStringToObject(root, "type", "MIA");
cJSON_AddNumberToObject(root, "isMissionTarget", m->isMissionTarget);
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -33,11 +33,13 @@ static int exitMission;
Entity *initTeeka(void)
{
Unit *u;
u = createUnit();
u->unitType = "Teeka";
u->type = ET_TEEKA;
u->flags |= EF_IMMUNE;
u->action = lookForEnemies;
@ -49,15 +51,15 @@ Entity *initTeeka(void)
u->sprite[FACING_DIE] = getSprite("TeekaLeft");
u->health = u->healthMax = 9999;
superTick = u->tick;
u->tick = tick;
exitMission = 0;
aimedSprite = getSprite("AimedShot");
return (Entity*)u;
}
@ -85,13 +87,13 @@ static void lookForEnemies(void)
Entity *e;
float distance, range;
Unit *u;
u = (Unit*)self;
u->thinkTime = rrnd(FPS / 2, FPS);
target = NULL;
distance = 800;
for (e = world.entityHead.next ; e != NULL ; e = e->next)
@ -132,9 +134,9 @@ static void lookForEnemies(void)
static void preFire(void)
{
Unit *u;
u = (Unit*)self;
if (u->reload > 0)
{
return;
@ -146,7 +148,7 @@ static void preFire(void)
}
attack();
if (--u->shotsToFire <= 0)
{
u->thinkTime = FPS;
@ -158,12 +160,10 @@ static void attack(void)
{
Bullet *bullet;
float dx, dy;
getSlope(target->x, target->y, self->x, self->y, &dx, &dy);
bullet = createBaseBullet((Unit*)self);
bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3;
bullet = createBaseBullet((Unit*)self, aimedSprite->w);
bullet->facing = self->facing;
bullet->damage = 1;
bullet->owner = self;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../common.h"
extern void addTeleportStars(Entity *e);
extern Bullet *createBaseBullet(Unit *owner);
extern Bullet *createBaseBullet(Unit *owner, int bulletWidth);
extern Unit *createUnit(void);
extern int getDistance(int x1, int y1, int x2, int y2);
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -23,16 +23,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Entity *initBlaze(void)
{
Boss *b;
b = initBlobBoss();
b->weakAgainst = ENV_WATER;
STRNCPY(b->name, "Blaze", MAX_NAME_LENGTH);
b->sprite[FACING_LEFT] = getSprite("BlazeLeft");
b->sprite[FACING_RIGHT] = getSprite("BlazeRight");
b->sprite[FACING_DIE] = getSprite("BlazeSpin");
return (Entity*)b;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -40,17 +40,17 @@ static Sprite *aimedSprite;
Boss *initBlobBoss(void)
{
Boss *b;
b = initBoss();
b->flags |= EF_HALT_AT_EDGE;
b->health = b->healthMax = 250;
b->teleportTimer = FPS * rrnd(4, 6);
superAnimate = b->animate;
b->activate = activate;
b->action = walk;
b->walk = walk;
@ -60,9 +60,9 @@ Boss *initBlobBoss(void)
b->animate = animate;
b->applyDamage = applyDamage;
b->die = die1;
aimedSprite = getSprite("AimedShot");
return b;
}
@ -83,9 +83,9 @@ static void activate(int activate)
static void tick(void)
{
Boss *b;
b = (Boss*)self;
if (b->health > 0)
{
b->stunTimer = MAX(b->stunTimer - 1, 0);
@ -95,7 +95,7 @@ static void tick(void)
b->health -= 2;
world.boss = b;
if (b->stunTimer == 0)
{
teleport();
@ -125,9 +125,9 @@ static void tick(void)
static void changeEnvironment()
{
Boss *b;
b = (Boss*)self;
if (b->environment == b->weakAgainst)
{
b->teleportTimer = 0;
@ -143,9 +143,9 @@ static void changeEnvironment()
static void die1(void)
{
Boss *b;
b = (Boss*)self;
b->flags |= EF_BOUNCES;
b->thinkTime = 0;
@ -176,7 +176,7 @@ static void die1(void)
playBattleSound(SND_DEATH_3, b->uniqueId % MAX_SND_CHANNELS, b->x, b->y);
break;
}
b->action = die2;
}
@ -184,9 +184,9 @@ static SDL_Rect *getCurrentSprite(void)
{
Boss *b;
Sprite *s;
b = (Boss*)self;
s = (b->stunTimer > 0 || b->health <= 0) ? b->sprite[FACING_DIE] : b->sprite[b->facing];
if (self->spriteFrame >= s->numFrames)
@ -194,20 +194,20 @@ static SDL_Rect *getCurrentSprite(void)
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "WARNING: %s (%d) bad sprite frames - %d > %d\n", self->name, self->type, self->spriteFrame, s->numFrames);
self->spriteFrame = 0;
}
return &s->frames[self->spriteFrame]->rect;
}
static void animate(void)
{
Boss *b;
b = (Boss*)self;
if (b->alive != ALIVE_ALIVE || b->stunTimer > 0)
{
b->facing = FACING_DIE;
superAnimate();
}
else if (b->dx != 0)
@ -219,9 +219,9 @@ static void animate(void)
static void lookForPlayer(void)
{
Boss *b;
b = (Boss*)self;
b->thinkTime = rrnd(0, FPS / 2);
if (getDistance(world.bob->x, world.bob->y, b->x, b->y) > 650)
@ -248,9 +248,9 @@ static void lookForPlayer(void)
static void moveTowardsPlayer(void)
{
Boss *b;
b = (Boss*)self;
b->dx = 0;
if (rand() % 100 < 20)
@ -282,9 +282,9 @@ static void moveTowardsPlayer(void)
static void preFire(void)
{
Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{
return;
@ -305,7 +305,7 @@ static void attack(void)
Bullet *bullet;
float dx, dy;
int bx, by;
if (self->facing != FACING_DIE)
{
bx = (int) (world.bob->x + rrnd(-8, 24));
@ -313,9 +313,7 @@ static void attack(void)
getSlope(bx, by, self->x, self->y, &dx, &dy);
bullet = createBaseBullet((Unit*)self);
bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3;
bullet = createBaseBullet((Unit*)self, aimedSprite->w);
bullet->facing = self->facing;
bullet->damage = 1;
bullet->owner = self;
@ -339,9 +337,9 @@ static void walk(void)
void reappear(void)
{
int valid, r;
valid = 0;
do
{
r = (int) (rand() % MAX_CHECKPOINTS);
@ -350,15 +348,15 @@ void reappear(void)
valid = (self->x != 0 && self->y != 0);
}
while (!valid);
self->y -= (self->h + 10);
walk();
self->flags &= ~EF_GONE;
addTeleportStars(self);
playBattleSound(SND_APPEAR, -1, self->x, self->y);
}
@ -391,9 +389,9 @@ static void teleport(void)
static void die2(void)
{
Boss *b;
b = (Boss*)self;
b->health--;
if (b->health <= -FPS)
@ -415,7 +413,7 @@ static void die2(void)
{
awardTrophy("BLAZE_FROST");
}
b->action = entityIdle;
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern void addTeleportStars(Entity *e);
extern void awardTrophy(char *id);
extern Bullet *createBaseBullet(Unit *owner);
extern Bullet *createBaseBullet(Unit *owner, int bulletWidth);
extern int enemyCanSeePlayer(Entity *e);
extern void entityIdle(void);
extern int getDistance(int x1, int y1, int x2, int y2);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -27,16 +27,16 @@ static void init(void);
Boss *initBoss(void)
{
Boss *b;
b = malloc(sizeof(Boss));
memset(b, 0, sizeof(Boss));
initEntity((Entity*)b);
b->type = ET_BOSS;
b->sprite[FACING_LEFT] = b->sprite[FACING_RIGHT] = b->sprite[FACING_DIE] = getSprite("Boss");
b->isMissionTarget = 1;
b->spriteFrame = 0;
@ -45,11 +45,11 @@ Boss *initBoss(void)
world.boss = b;
b->flags |= EF_ALWAYS_PROCESS | EF_BOMB_SHIELD | EF_GONE;
b->init = init;
b->load = load;
b->save = save;
return b;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -43,19 +43,19 @@ static Sprite *plasmaSprite[2];
Entity *initEyeDroidCommander(void)
{
Boss *b;
b = initBoss();
STRNCPY(b->name, "EyeDroid Commander", MAX_NAME_LENGTH);
b->sprite[FACING_LEFT] = getSprite("DroidCommanderLeft");
b->sprite[FACING_RIGHT] = getSprite("DroidCommanderRight");
b->sprite[FACING_DIE] = getSprite("DroidCommanderDie");
b->flags |= EF_WEIGHTLESS | EF_EXPLODES;
b->health = b->healthMax = 250;
b->action = walk;
b->walk = walk;
b->tick = tick;
@ -65,15 +65,15 @@ Entity *initEyeDroidCommander(void)
b->getCurrentSprite = getCurrentSprite;
brakingTimer = 0;
aimedSprite = getSprite("AimedShot");
missileSprite[0] = getSprite("MissileRight");
missileSprite[1] = getSprite("MissileLeft");
plasmaSprite[0] = getSprite("PlasmaRight");
plasmaSprite[1] = getSprite("PlasmaLeft");
return (Entity*)b;
}
@ -91,9 +91,9 @@ static void activate(int activate)
static void tick(void)
{
Boss *b;
b = (Boss*)self;
if (b->health > 0)
{
b->facing = (world.bob->x < b->x) ? FACING_LEFT : FACING_RIGHT;
@ -117,22 +117,22 @@ static void tick(void)
static void lookForPlayer(void)
{
float distance;
self->thinkTime = rrnd(0, FPS / 2);
if (rand() % 100 < 5)
{
brakingTimer = rrnd(60, 120);
}
distance = getDistance(world.bob->x, world.bob->y, self->x, self->y);
if (distance > SCREEN_HEIGHT)
if (distance > app.config.winHeight)
{
moveTowardsPlayer(1);
return;
}
if (!enemyCanSeePlayer(self))
{
moveTowardsPlayer(1);
@ -143,8 +143,8 @@ static void lookForPlayer(void)
{
selectWeapon();
}
if (distance < SCREEN_HEIGHT / 4)
if (distance < app.config.winHeight / 4)
{
moveTowardsPlayer(-6);
}
@ -157,9 +157,9 @@ static void lookForPlayer(void)
static void selectWeapon(void)
{
Boss *b;
b = (Boss*)self;
if (world.bob->isOnGround || fabs(self->y - world.bob->y) > 64)
{
b->weaponType = WPN_AIMED_PISTOL;
@ -188,9 +188,9 @@ static void walk(void)
static void moveTowardsPlayer(int dir)
{
float vel;
vel = 0.5 * dir;
if (brakingTimer == 0)
{
if (world.bob->x < self->x)
@ -221,9 +221,9 @@ static void moveTowardsPlayer(int dir)
static void preFire(void)
{
Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{
return;
@ -242,11 +242,11 @@ static void preFire(void)
static void attack(void)
{
Boss *b;
if (self->facing != FACING_DIE)
{
b = (Boss*)self;
switch (b->weaponType)
{
case WPN_AIMED_PISTOL:
@ -270,17 +270,15 @@ static void attackPistol(void)
float dx, dy;
Bullet *bullet;
Boss *b;
b = (Boss*)self;
bx = world.bob->x + rrnd(-8, 24);
by = world.bob->y + rrnd(-8, 24);
getSlope(bx, by, self->x, self->y, &dx, &dy);
bullet = createBaseBullet((Unit*)self);
bullet->x = (self->x + self->w / 2);
bullet->y = (self->y + self->h / 2) - 3;
bullet = createBaseBullet((Unit*)self, aimedSprite->w);
bullet->facing = self->facing;
bullet->damage = 1;
bullet->owner = self;
@ -299,12 +297,10 @@ static void attackPlasma(void)
{
Boss *b;
Bullet *bullet;
b = (Boss*)self;
bullet = createBaseBullet((Unit*)self);
bullet->x = (self->x + self->w / 2);
bullet->y = (self->y + self->h / 2) - 3;
bullet = createBaseBullet((Unit*)self, plasmaSprite[0]->w);
bullet->facing = self->facing;
bullet->damage = 2;
bullet->owner = self;
@ -324,19 +320,17 @@ static void attackMissile(void)
{
Boss *b;
Bullet *missile;
b = (Boss*)self;
missile = createBaseBullet((Unit*)self);
missile->x = b->x + b->w / 2;
missile->y = b->y + b->h / 2;
missile = createBaseBullet((Unit*)self, missileSprite[0]->w);
missile->facing = b->facing;
missile->dx = b->facing == FACING_RIGHT ? 15 : -15;
missile->owner = self;
missile->health = FPS * 3;
missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1];
initMissile(missile);
b->reload = 15;
@ -358,9 +352,9 @@ static void applyDamage(int amount)
static void die(void)
{
Boss *b;
b = (Boss*)self;
b->dx = (randF() - randF()) * 3;
b->spriteTime = 0;
@ -385,9 +379,9 @@ static void die(void)
static void die2()
{
Boss *b;
b = (Boss*)self;
if (b->isOnGround)
{
addTeleportStars(self);
@ -404,7 +398,7 @@ static void die2()
awardTrophy("EYEDROID_COMMANDER");
game.stats[STAT_ENEMIES_KILLED]++;
b->action = entityIdle;
}
}
@ -412,14 +406,14 @@ static void die2()
static SDL_Rect *getCurrentSprite(void)
{
Sprite *s;
s = (self->alive == ALIVE_ALIVE) ? self->sprite[self->facing] : self->sprite[FACING_DIE];
if (self->spriteFrame >= s->numFrames)
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "WARNING: %s (%d) bad sprite frames - %d > %d\n", self->name, self->type, self->spriteFrame, s->numFrames);
self->spriteFrame = 0;
}
return &s->frames[self->spriteFrame]->rect;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -24,7 +24,7 @@ extern void addExplosion(float x, float y, int radius, Entity *owner);
extern void addSmokeParticles(float x, float y, int rising);
extern void addTeleportStars(Entity *e);
extern void awardTrophy(char *id);
extern Bullet *createBaseBullet(Unit *owner);
extern Bullet *createBaseBullet(Unit *owner, int bulletWidth);
extern int enemyCanSeePlayer(Entity *e);
extern void entityIdle(void);
extern int getDistance(int x1, int y1, int x2, int y2);
@ -39,6 +39,7 @@ extern double randF(void);
extern int rrnd(int low, int high);
extern void updateObjective(char *targetName);
extern App app;
extern Entity *self;
extern Game game;
extern World world;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -23,16 +23,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Entity *initFrost(void)
{
Boss *b;
b = initBlobBoss();
b->weakAgainst = ENV_LAVA;
STRNCPY(b->name, "Frost", MAX_NAME_LENGTH);
b->sprite[FACING_LEFT] = getSprite("FrostLeft");
b->sprite[FACING_RIGHT] = getSprite("FrostRight");
b->sprite[FACING_DIE] = getSprite("FrostSpin");
return (Entity*)b;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -42,7 +42,7 @@ static Sprite *aimedSprite;
Entity *initTankCommander(void)
{
Boss *b;
b = initBoss();
STRNCPY(b->name, "Tank Commander", MAX_NAME_LENGTH);
@ -64,25 +64,25 @@ Entity *initTankCommander(void)
b->getCollisionBounds = getCollisionBounds;
brakingTimer = 0;
aimedSprite = getSprite("AimedShot");
missileSprite[0] = getSprite("MissileRight");
missileSprite[1] = getSprite("MissileLeft");
tankTrack = initTankTrack(b);
world.boss = b;
return (Entity*)b;
}
static void activate(int activate)
{
Boss *b;
b = (Boss*)self;
b->flags &= ~EF_GONE;
tankTrack->flags &= ~EF_GONE;
@ -97,9 +97,9 @@ static void activate(int activate)
static void tick(void)
{
Boss *b;
b = (Boss*)self;
if (b->health > 0)
{
b->facing = (world.bob->x < b->x) ? FACING_LEFT : FACING_RIGHT;
@ -119,9 +119,9 @@ static void tick(void)
static void lookForPlayer(void)
{
Boss *b;
b = (Boss*)self;
b->thinkTime = rrnd(0, FPS / 2);
if (rand() % 10 == 0)
@ -175,9 +175,9 @@ static void moveTowardsPlayer(void)
static void selectWeapon(void)
{
Boss *b;
b = (Boss*)self;
if (fabs(b->y - world.bob->y) > 64)
{
b->weaponType = WPN_AIMED_PISTOL;
@ -195,9 +195,9 @@ static void selectWeapon(void)
static void preFire(void)
{
Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{
moveTowardsPlayer();
@ -217,11 +217,11 @@ static void preFire(void)
static void attack(void)
{
Boss *b;
if (self->facing != FACING_DIE)
{
b = (Boss*)self;
switch (b->weaponType)
{
case WPN_AIMED_PISTOL:
@ -242,15 +242,15 @@ static void attackPistol(void)
float dx, dy;
Bullet *bullet;
Boss *b;
b = (Boss*)self;
bx = world.bob->x + rrnd(-8, 24);
by = world.bob->y + rrnd(-8, 24);
getSlope(bx, by, b->x, b->y, &dx, &dy);
bullet = createBaseBullet((Unit*)self);
bullet = createBaseBullet((Unit*)self, aimedSprite->w);
bullet->x = (b->x + b->w / 2);
bullet->y = b->y + 30;
bullet->facing = b->facing;
@ -271,10 +271,10 @@ static void attackMissile(void)
{
Bullet *missile;
Boss *b;
b = (Boss*)self;
missile = createBaseBullet((Unit*)self);
missile = createBaseBullet((Unit*)self, missileSprite[0]->w);
missile->x = b->x + b->w / 2;
missile->y = b->y + 30;
missile->facing = b->facing;
@ -287,7 +287,7 @@ static void attackMissile(void)
missile->sprite[1] = missileSprite[1];
b->reload = 15;
initMissile(missile);
playBattleSound(SND_MISSILE, b->uniqueId % MAX_SND_CHANNELS, b->x, b->y);
@ -296,9 +296,9 @@ static void attackMissile(void)
static void die1(void)
{
Boss *b;
b = (Boss*)self;
b->flags |= EF_BOUNCES;
b->action = die2;
@ -312,7 +312,7 @@ static void die2(void)
{
int mx, my;
Boss *b;
b = (Boss*)self;
b->health--;
@ -321,7 +321,7 @@ static void die2(void)
{
mx = (int) ((b->x + (b->w / 2)) / MAP_TILE_SIZE);
my = (int) ((b->y + b->h) / MAP_TILE_SIZE);
addScorchDecal(mx, my);
addExplosion(b->x + rand() % b->w, b->y + rand() % b->h, 50, self);
@ -345,7 +345,7 @@ static void die2(void)
awardTrophy("TANK_COMMANDER");
game.stats[STAT_ENEMIES_KILLED]++;
b->action = entityIdle;
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -24,7 +24,7 @@ extern void addExplosion(float x, float y, int radius, Entity *owner);
extern void addScorchDecal(int x, int y);
extern void addTeleportStars(Entity *e);
extern void awardTrophy(char *id);
extern Bullet *createBaseBullet(Unit *owner);
extern Bullet *createBaseBullet(Unit *owner, int bulletWidth);
extern int enemyCanSeePlayer(Entity *e);
extern void entityIdle(void);
extern int getDistance(int x1, int y1, int x2, int y2);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -31,7 +31,7 @@ static void getCollisionBounds(SDL_Rect *r);
Entity *initTankTrack(Boss *owner)
{
Boss *b;
b = initBoss();
superAnimate = b->animate;
@ -51,7 +51,7 @@ Entity *initTankTrack(Boss *owner)
b->getCollisionBounds = getCollisionBounds;
tankCommander = owner;
return (Entity*)b;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -23,16 +23,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void tick(void);
static void touch(Entity *other);
Bullet *createBaseBullet(Unit *owner)
Bullet *createBaseBullet(Unit *owner, int bulletWidth)
{
Bullet *bullet;
bullet = malloc(sizeof(Bullet));
memset(bullet, 0, sizeof(Bullet));
initEntity((Entity*)bullet);
bullet->x = (owner->x + owner->w / 2);
bullet->x = owner->x + (owner->w / 2) - (bulletWidth / 2);
bullet->y = (owner->y + owner->h / 2) - 3;
bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15;
bullet->facing = owner->facing;
@ -43,7 +43,7 @@ Bullet *createBaseBullet(Unit *owner)
bullet->tick = tick;
bullet->touch = touch;
bullet->spriteFrame = 0;
return bullet;
@ -65,7 +65,7 @@ static void tick(void)
/* don't allow the player to kill everything on the map by firing constantly */
if (b->owner->type == ET_BOB)
{
if (b->x < camera.x || b->y < camera.y || b->x > camera.x + SCREEN_WIDTH || b->y > camera.y + SCREEN_HEIGHT)
if (b->x < camera.x || b->y < camera.y || b->x > camera.x + app.config.winWidth || b->y > camera.y + app.config.winHeight)
{
b->alive = ALIVE_DEAD;
}
@ -104,7 +104,7 @@ static void touch(Entity *other)
b->owner->type != other->type &&
!((b->owner->type == ET_TEEKA && other->type == ET_BOB) || (b->owner->type == ET_BOB && other->type == ET_TEEKA))
);
if (canHit)
{
swapSelf(other);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -22,11 +22,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern void addSmallFleshChunk(float x, float y);
extern void addSparkParticles(float x, float y);
extern Bullet *createBaseBullet(Unit *owner);
extern void initEntity(Entity *e);
extern void playBattleSound(int snd, int ch, int x, int y);
extern void swapSelf(Entity *e);
extern App app;
extern Camera camera;
extern Entity *self;
extern Game game;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -30,7 +30,7 @@ static void explode(void);
void initGrenade(Bullet *b)
{
b->flags = EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_FRICTIONLESS | EF_NO_TELEPORT;
superBounce = b->bounce;
b->tick = tick;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -61,7 +61,7 @@ static void touch(Entity *other)
b->owner->type != other->type &&
!((b->owner->type == ET_TEEKA && other->type == ET_BOB) || (b->owner->type == ET_BOB && other->type == ET_TEEKA))
);
if (canHit)
{
if (other->flags & EF_EXPLODES)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -32,11 +32,11 @@ static void getCollisionBounds(SDL_Rect *r);
Entity *initCannon(void)
{
Unit *u;
u = createUnit();
u->unitType = "Cannon";
u->type = ET_ENEMY;
u->sprite[FACING_LEFT] = getSprite("CannonLeft");
@ -62,7 +62,7 @@ Entity *initCannon(void)
u->die = die;
u->canFire = canFire;
u->getCollisionBounds = getCollisionBounds;
return (Entity*)u;
}
@ -87,7 +87,7 @@ static void die(void)
u->flags |= EF_BOUNCES | EF_ALWAYS_PROCESS;
u->action = die2;
u->facing = FACING_DIE;
u->thinkTime = 0;
u->spriteTime = 0;
@ -107,7 +107,7 @@ static void die2(void)
{
Unit *u;
int mx, my;
u = (Unit*)self;
if (--u->health % 3 == 0)
@ -117,7 +117,7 @@ static void die2(void)
addScorchDecal(mx, my);
addExplosion(u->x, u->y, 50, self);
throwDebris(u->x + u->w / 2, u->y + u->h / 2, 1);
}
@ -130,7 +130,7 @@ static void die2(void)
dropCarriedItem();
u->alive = ALIVE_DEAD;
addRandomWeapon(u->x, u->y);
}
}
@ -146,7 +146,7 @@ static void lookForPlayer(void)
{
Unit *u;
int r;
u = (Unit*)self;
u->thinkTime = rrnd(FPS / 2, FPS);
@ -192,9 +192,9 @@ static void lookForPlayer(void)
static void preFire(void)
{
Unit *u;
u = (Unit*)self;
u->facing = (world.bob->x < u->x) ? FACING_LEFT : FACING_RIGHT;
if (u->reload > 0)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -28,9 +28,9 @@ static void changeEnvironment(void);
void initDebris(Decoration *d)
{
initEntity((Entity*)d);
d->type = ET_DECORATION;
d->effectType = rand() % 2;
d->spriteFrame = 0;
@ -51,9 +51,9 @@ static void tick(void)
static void action(void)
{
Decoration *d;
d = (Decoration*)self;
if (d->effectType == 0)
{
addFlameParticles(d->x + (rand() % d->w), d->y + (rand() % d->h), d->isOnGround);
@ -69,9 +69,9 @@ static void action(void)
static void touch(Entity *other)
{
Decoration *d;
d = (Decoration*)self;
if (other == NULL)
{
d->dx *= 0.9;
@ -87,7 +87,7 @@ static void changeEnvironment(void)
case ENV_WATER:
self->alive = ALIVE_DEAD;
break;
default:
break;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -27,11 +27,11 @@ static void touch(Entity *other);
void initFleshChunk(Decoration *d)
{
initEntity((Entity*)d);
d->type = ET_DECORATION;
d->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_NO_TELEPORT | EF_CRUSHABLE;
if (app.config.blood != 2)
{
d->flags |= EF_KILL_OFFSCREEN;
@ -49,20 +49,20 @@ void initFleshChunk(Decoration *d)
static void tick(void)
{
Decoration *d;
d = (Decoration*)self;
d->health--;
d->bleedTime--;
}
static void action(void)
{
Decoration *d;
d = (Decoration*)self;
if (d->bleedTime > 0)
{
addBlood(d->x + (rand() % d->w), d->y + (rand() % d->h));
@ -74,11 +74,11 @@ static void action(void)
static void touch(Entity *other)
{
int mx, my;
if (other == NULL)
{
self->dx *= 0.9;
if (app.config.blood == 2)
{
mx = (int) ((self->x + (self->w / 2)) / MAP_TILE_SIZE);

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -39,7 +39,7 @@ static void save(cJSON *root);
void initEntity(Entity *e)
{
e->uniqueId = world.entityCounter++;
e->environment = ENV_AIR;
e->alive = ALIVE_ALIVE;
@ -55,10 +55,10 @@ void initEntity(Entity *e)
e->flags = 0;
e->thinkTime = 0;
e->spriteFrame = -1;
e->spriteTime = 0;
e->init = init;
e->reset = reset;
e->action = action;
@ -72,10 +72,10 @@ void initEntity(Entity *e)
e->die = die;
e->changeEnvironment = changeEnvironment;
e->getCollisionBounds = getCollisionBounds;
e->load = load;
e->save = save;
world.entityTail->next = e;
world.entityTail = e;
}
@ -97,9 +97,9 @@ static void action(void)
static void animate(void)
{
Sprite *s;
s = self->sprite[self->facing];
if (self->spriteTime != -1)
{
if (--self->spriteTime <= 0)
@ -108,7 +108,7 @@ static void animate(void)
{
self->spriteFrame = 0;
}
self->spriteTime = self->sprite[self->facing]->times[self->spriteFrame];
}
}
@ -169,15 +169,15 @@ void entityIdle(void)
static SDL_Rect *getCurrentSprite(void)
{
Sprite *s;
s = self->sprite[self->facing];
if (self->spriteFrame >= s->numFrames)
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "WARNING: %s (%d) bad sprite frames - %d > %d\n", self->name, self->type, self->spriteFrame, s->numFrames);
self->spriteFrame = 0;
}
return &s->frames[self->spriteFrame]->rect;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -31,7 +31,7 @@ void initEntityFactory(void)
{
memset(&head, 0, sizeof(EntityDef));
tail = &head;
addEntityDef("AquaBlob", initAquaBlob);
addEntityDef("PistolBlob", initPistolBlob);
addEntityDef("PistolEyeDroid", initPistolDroid);
@ -54,11 +54,11 @@ void initEntityFactory(void)
addEntityDef("Frost", initFrost);
addEntityDef("EyeDroidCommander", initEyeDroidCommander);
addEntityDef("TankCommander", initTankCommander);
addEntityDef("Bob", initBob);
addEntityDef("MIA", initMIA);
addEntityDef("Teeka", initTeeka);
addEntityDef("Item", initItem);
addEntityDef("BronzeKey", initBronzeKey);
addEntityDef("SilverKey", initSilverKey);
@ -69,10 +69,10 @@ void initEntityFactory(void)
addEntityDef("YellowKeycard", initYellowKeycard);
addEntityDef("WhiteKeycard", initWhiteKeycard);
addEntityDef("WeaponPickup", initWeaponPickup);
addEntityDef("Cell", initCell);
addEntityDef("Heart", initHeart);
addEntityDef("Exit", initExit);
addEntityDef("PowerPool", initPowerPool);
addEntityDef("Teleporter", initTeleporter);
@ -97,7 +97,7 @@ void initEntityFactory(void)
Entity *createEntity(char *name)
{
EntityDef *def;
for (def = head.next ; def != NULL ; def = def->next)
{
if (strcmp(def->name, name) == 0)
@ -106,22 +106,22 @@ Entity *createEntity(char *name)
return def->initFunc();
}
}
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "No such entity definition '%s'", name);
exit(1);
return NULL;
}
static void addEntityDef(char *name, Entity *(*initFunc)(void))
{
EntityDef *def;
def = malloc(sizeof(EntityDef));
memset(def, 0, sizeof(EntityDef));
tail->next = def;
tail = def;
STRNCPY(def->name, name, MAX_NAME_LENGTH);
def->initFunc = initFunc;
}
@ -131,11 +131,11 @@ static Entity *initGenericEvilBlob(void)
int r;
char name[MAX_NAME_LENGTH];
strcpy(name, "");
r = rand() % world.numEnemyTypes;
sprintf(name, "%sBlob", world.enemyTypes[r]);
return createEntity(name);
}
@ -144,10 +144,10 @@ static Entity *initGenericEyeDroid(void)
int r;
char name[MAX_NAME_LENGTH];
strcpy(name, "");
r = rand() % world.numEnemyTypes;
sprintf(name, "%sEyeDroid", world.enemyTypes[r]);
return createEntity(name);
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,9 +25,9 @@ static int canFire(Entity *target);
Entity *initAquaBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "AquaBlob";
u->sprite[FACING_LEFT] = getSprite("AquaBlobLeft");
@ -41,7 +41,7 @@ Entity *initAquaBlob(void)
u->maxShotsToFire = 3;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -30,7 +30,7 @@ static void animate(void);
Unit *createEvilBlob(void)
{
Unit *u;
u = createUnit();
u->reload = 0;
@ -38,7 +38,7 @@ Unit *createEvilBlob(void)
u->returnToStartTimer = 0;
u->flags |= EF_HALT_AT_EDGE;
superAnimate = u->animate;
u->action = lookForPlayer;
@ -249,14 +249,14 @@ static void lookForPlayer(void)
patrol();
return;
}
r = randF();
if (world.missionType == MT_OUTPOST)
if (world.missionType == MT_OUTPOST || game.plus)
{
r = randF() * 0.65;
}
if (u->isMissionTarget)
{
r = randF() * 0.3;
@ -294,7 +294,7 @@ static void die(void)
u->flags &= ~(EF_HALT_AT_EDGE | EF_GONE);
u->action = die2;
u->facing = FACING_DIE;
u->thinkTime = 0;
u->spriteTime = 0;
@ -331,8 +331,8 @@ static void animate(void)
if (self->alive != ALIVE_ALIVE)
{
self->facing = FACING_DIE;
superAnimate();
superAnimate();
}
else if (self->dx != 0)
{

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -27,18 +27,18 @@ static int canFire(Entity *target);
Entity *initGrenadeBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "GrenadeBlob";
u->sprite[FACING_LEFT] = getSprite("GrenadeBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("GrenadeBlobRight");
u->sprite[FACING_DIE] = getSprite("GrenadeBlobSpin");
u->weaponType = WPN_GRENADES;
u->maxShotsToFire = 1;
superPreFire = u->preFire;
u->preFire = preFire;
@ -50,9 +50,9 @@ Entity *initGrenadeBlob(void)
static void preFire(void)
{
Unit *u;
u = (Unit*)self;
superPreFire();
if (u->shotsToFire == 0)

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initLaserBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "LaserBlob";
u->sprite[FACING_LEFT] = getSprite("LaserBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("LaserBlobRight");
u->sprite[FACING_DIE] = getSprite("LaserBlobSpin");
@ -39,7 +39,7 @@ Entity *initLaserBlob(void)
u->maxShotsToFire = 1;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initMachineGunBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "MachineGunBlob";
u->sprite[FACING_LEFT] = getSprite("MachineGunBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("MachineGunBlobRight");
u->sprite[FACING_DIE] = getSprite("MachineGunBlobSpin");
@ -39,7 +39,7 @@ Entity *initMachineGunBlob(void)
u->maxShotsToFire = 5;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initPistolBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "PistolBlob";
u->sprite[FACING_LEFT] = getSprite("PistolBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("PistolBlobRight");
u->sprite[FACING_DIE] = getSprite("PistolBlobSpin");
@ -39,7 +39,7 @@ Entity *initPistolBlob(void)
u->maxShotsToFire = 3;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initPlasmaBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "PlasmaBlob";
u->sprite[FACING_LEFT] = getSprite("PlasmaBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("PlasmaBlobRight");
u->sprite[FACING_DIE] = getSprite("PlasmaBlobSpin");
@ -39,7 +39,7 @@ Entity *initPlasmaBlob(void)
u->maxShotsToFire = 6;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initShotgunBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "ShotgunBlob";
u->sprite[FACING_LEFT] = getSprite("ShotgunBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("ShotgunBlobRight");
u->sprite[FACING_DIE] = getSprite("ShotgunBlobSpin");

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initSpreadGunBlob(void)
{
Unit *u;
u = createEvilBlob();
u->unitType = "SpreadGunBlob";
u->sprite[FACING_LEFT] = getSprite("SpreadGunBlobLeft");
u->sprite[FACING_RIGHT] = getSprite("SpreadGunBlobRight");
u->sprite[FACING_DIE] = getSprite("SpreadGunBlobSpin");
@ -39,7 +39,7 @@ Entity *initSpreadGunBlob(void)
u->maxShotsToFire = 3;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -30,7 +30,7 @@ static void (*superTouch)(Entity *other);
Unit *createEyeDroid(void)
{
Unit *u;
u = createUnit();
u->flags |= EF_WEIGHTLESS | EF_HALT_AT_EDGE | EF_EXPLODES;
@ -222,12 +222,12 @@ static void lookForPlayer(void)
}
r = randF();
if (world.missionType == MT_OUTPOST)
if (world.missionType == MT_OUTPOST || game.plus)
{
r = randF() * 0.65;
}
if (u->isMissionTarget)
{
r = randF() * 0.3;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -27,23 +27,23 @@ static int canFire(Entity *target);
Entity *initGrenadeDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "GrenadeEyeDroid";
u->sprite[FACING_LEFT] = getSprite("GrenadeDroidLeft");
u->sprite[FACING_RIGHT] = getSprite("GrenadeDroidRight");
u->sprite[FACING_DIE] = getSprite("GrenadeDroidDie");
u->weaponType = WPN_GRENADES;
u->maxShotsToFire = 1;
superPreFire = u->preFire;
u->preFire = preFire;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,9 +25,9 @@ static int canFire(Entity *target);
Entity *initLaserDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "LaserEyeDroid";
u->sprite[FACING_LEFT] = getSprite("LaserDroidLeft");
@ -39,7 +39,7 @@ Entity *initLaserDroid(void)
u->maxShotsToFire = 1;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,9 +25,9 @@ static int canFire(Entity *target);
Entity *initMachineGunDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "MachineGunEyeDroid";
u->sprite[FACING_LEFT] = getSprite("MachineGunDroidLeft");
@ -39,7 +39,7 @@ Entity *initMachineGunDroid(void)
u->maxShotsToFire = 5;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,11 +25,11 @@ static int canFire(Entity *target);
Entity *initPistolDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "PistolEyeDroid";
u->sprite[FACING_LEFT] = getSprite("PistolDroidLeft");
u->sprite[FACING_RIGHT] = getSprite("PistolDroidRight");
u->sprite[FACING_DIE] = getSprite("PistolDroidDie");
@ -39,7 +39,7 @@ Entity *initPistolDroid(void)
u->maxShotsToFire = 3;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@ -25,9 +25,9 @@ static int canFire(Entity *target);
Entity *initPlasmaDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "PlasmaEyeDroid";
u->sprite[FACING_LEFT] = getSprite("PlasmaDroidLeft");
@ -39,7 +39,7 @@ Entity *initPlasmaDroid(void)
u->maxShotsToFire = 6;
u->canFire = canFire;
return (Entity*)u;
}

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2018 Parallel Realities
Copyright (C) 2018-2019 Parallel Realities
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License

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