Compare commits

...

35 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 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 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 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
242 changed files with 3721 additions and 2681 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@ blobwarsAttrition
.DS_Store
dist/*
/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

@ -10,7 +10,7 @@ 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.
@ -24,9 +24,9 @@ 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.

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 = 3
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

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Blob Wars : Attrition\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-29 07:46:49+0100\n"
"POT-Creation-Date: 2018-05-12 11:50:05+0100\n"
"PO-Revision-Date: ???\n"
"Last-Translator: ???\n"
"Language-Team: ???\n"
@ -265,12 +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 ""
@ -433,9 +439,6 @@ msgstr ""
msgid "Find Teeka"
msgstr ""
msgid "Defeat enemies"
msgstr ""
msgid "Destroy Toxic Barrels"
msgstr ""

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
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>
@ -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>
@ -298,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>

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++;
@ -104,7 +104,7 @@ void addExplosion(float x, float y, int radius, Entity *owner)
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

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,7 +68,7 @@ void initWeapons(void)
void firePistol(void)
{
Bullet *bullet;
if (world.bob->facing != FACING_DIE)
{
bullet = createBaseBullet((Unit*)world.bob, bulletSprite[0]->frames[0]->rect.w);
@ -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));
@ -112,7 +112,7 @@ void fireAimedShot(Unit *owner)
void fireMachineGun(Unit *owner)
{
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
bullet = createBaseBullet(owner, bulletSprite[0]->w);
@ -128,7 +128,7 @@ void fireMachineGun(Unit *owner)
void firePlasma(Unit *owner)
{
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
bullet = createBaseBullet(owner, plasmaSprite[0]->w);
@ -173,7 +173,7 @@ void fireSpread(Unit *owner, int numberOfShots)
void fireLaser(Unit *owner)
{
Bullet *laser;
if (owner->facing != FACING_DIE)
{
laser = createBaseBullet(owner, laserSprite[0]->w);
@ -193,7 +193,7 @@ void fireLaser(Unit *owner)
void fireGrenade(Unit *owner)
{
Bullet *grenade;
if (owner->facing != FACING_DIE)
{
grenade = createBaseBullet(owner, grenadeSprite->w);
@ -217,7 +217,7 @@ void fireShotgun(Unit *owner)
int i;
float dx, dy;
Bullet *bullet;
if (owner->facing != FACING_DIE)
{
for (i = 0 ; i < 8 ; i++)
@ -243,7 +243,7 @@ void fireShotgun(Unit *owner)
void fireMissile(Unit *owner)
{
Bullet *missile;
if (owner->facing != FACING_DIE)
{
missile = createBaseBullet(owner, missileSprite[0]->w);

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
@ -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,7 +53,7 @@ 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
@ -63,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
@ -79,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
@ -144,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
@ -431,5 +435,13 @@ enum
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,6 +705,11 @@ 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)
@ -714,7 +719,7 @@ static void save(cJSON *root)
{
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,13 +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;
@ -51,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;
}
@ -87,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)
@ -134,9 +134,9 @@ static void lookForEnemies(void)
static void preFire(void)
{
Unit *u;
u = (Unit*)self;
if (u->reload > 0)
{
return;
@ -148,7 +148,7 @@ static void preFire(void)
}
attack();
if (--u->shotsToFire <= 0)
{
u->thinkTime = FPS;
@ -160,7 +160,7 @@ static void attack(void)
{
Bullet *bullet;
float dx, dy;
getSlope(target->x, target->y, self->x, self->y, &dx, &dy);
bullet = createBaseBullet((Unit*)self, aimedSprite->w);

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.
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));
@ -337,9 +337,9 @@ static void walk(void)
void reappear(void)
{
int valid, r;
valid = 0;
do
{
r = (int) (rand() % MAX_CHECKPOINTS);
@ -348,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);
}
@ -389,9 +389,9 @@ static void teleport(void)
static void die2(void)
{
Boss *b;
b = (Boss*)self;
b->health--;
if (b->health <= -FPS)
@ -413,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

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,9 +270,9 @@ 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);
@ -297,9 +297,9 @@ static void attackPlasma(void)
{
Boss *b;
Bullet *bullet;
b = (Boss*)self;
bullet = createBaseBullet((Unit*)self, plasmaSprite[0]->w);
bullet->facing = self->facing;
bullet->damage = 2;
@ -320,9 +320,9 @@ static void attackMissile(void)
{
Boss *b;
Bullet *missile;
b = (Boss*)self;
missile = createBaseBullet((Unit*)self, missileSprite[0]->w);
missile->facing = b->facing;
missile->dx = b->facing == FACING_RIGHT ? 15 : -15;
@ -330,7 +330,7 @@ static void attackMissile(void)
missile->health = FPS * 3;
missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1];
initMissile(missile);
b->reload = 15;
@ -352,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;
@ -379,9 +379,9 @@ static void die(void)
static void die2()
{
Boss *b;
b = (Boss*)self;
if (b->isOnGround)
{
addTeleportStars(self);
@ -398,7 +398,7 @@ static void die2()
awardTrophy("EYEDROID_COMMANDER");
game.stats[STAT_ENEMIES_KILLED]++;
b->action = entityIdle;
}
}
@ -406,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
@ -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,9 +242,9 @@ 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);
@ -271,7 +271,7 @@ static void attackMissile(void)
{
Bullet *missile;
Boss *b;
b = (Boss*)self;
missile = createBaseBullet((Unit*)self, missileSprite[0]->w);
@ -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

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
@ -26,12 +26,12 @@ static void touch(Entity *other);
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) - (bulletWidth / 2);
bullet->y = (owner->y + owner->h / 2) - 3;
bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15;
@ -43,7 +43,7 @@ Bullet *createBaseBullet(Unit *owner, int bulletWidth)
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
@ -26,6 +26,7 @@ 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

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 *initShotgunDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "ShotgunEyeDroid";
u->sprite[FACING_LEFT] = getSprite("ShotgunDroidLeft");

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 *initSpreadGunDroid(void)
{
Unit *u;
u = createEyeDroid();
u->unitType = "SpreadGunEyeDroid";
u->sprite[FACING_LEFT] = getSprite("SpreadGunDroidLeft");
@ -39,7 +39,7 @@ Entity *initSpreadGunDroid(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,23 +25,23 @@ static void touch(Entity *other);
Item *initBattery(void)
{
Item *i;
i = initConsumable();
i->spriteFrame = 0;
i->spriteTime = -1;
i->touch = touch;
return i;
}
static void touch(Entity *other)
{
Item *i;
i = (Item*)self;
if (touchedPlayer(other))
{
world.bob->power = MIN(world.bob->power + i->power, world.bob->powerMax);

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
@ -26,9 +26,9 @@ static void init(void);
Entity *initCell(void)
{
Item *i;
i = (Item*)createItem();
i->type = ET_CELL;
i->isMissionTarget = 1;
@ -42,13 +42,13 @@ Entity *initCell(void)
i->init = init;
i->touch = touch;
return (Entity*)i;
}
static void init(void)
{
if (game.isComplete && rand() % 3 > 0)
if ((game.isComplete && rand() % 3 > 0) || game.plus != PLUS_NONE)
{
self->alive = ALIVE_DEAD;
}

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