2017-11-02 21:01:40 +01:00
unit GameTutorial1;
2017-11-07 02:42:53 +01:00
//tutorial step1: player and target
//the player has an ammo capacity of 5 bullets, and the target heals itself each time the player reloads
//the task: destroy the target. (e.g add more bullets, make the bullets do more damage, change to code to instant kill, jump to the success code, ...)
2017-11-02 21:01:40 +01:00
{$mode objfpc} {$H+}
interface
uses
windows, Classes, SysUtils, gamepanel, guitextobject, staticguiobject, gamebase, player,
target, bullet, Dialogs, Graphics;
type
TGame1= class( TGameBase)
private
fpanel: Tgamepanel;
player: TPlayer;
target: Ttarget;
bullets: array [ 0 .. 4 ] of Tbullet; //max 5 bullets on the screen at once
reloading: qword;
reloadingtargetstarthp: integer ;
shotsfired: integer ;
lastshot: qword;
rotatedirection: single ;
status: TGUITextObject;
info: TGUITextObject;
infobutton: TStaticGUIObject;
2018-12-08 00:05:26 +01:00
2017-11-02 21:01:40 +01:00
function infoPopup( sender: tobject) : boolean ;
function HideInfo( sender: tobject) : boolean ;
public
procedure gametick( currentTime: qword; diff: integer ) ; override ;
procedure render; override ;
function KeyHandler( TGamePanel: TObject; keventtype: integer ; Key: Word ; Shift: TShiftState) : boolean ; override ;
constructor create( p: TGamePanel) ;
destructor destroy; override ;
end ;
implementation
2018-12-08 00:05:26 +01:00
uses registry;
2017-11-02 21:01:40 +01:00
function TGame1. KeyHandler( TGamePanel: TObject; keventtype: integer ; Key: Word ; Shift: TShiftState) : boolean ;
var
x: boolean ;
i: integer ;
ct: qword;
2018-05-15 01:43:19 +02:00
2017-11-02 21:01:40 +01:00
begin
2018-05-15 01:43:19 +02:00
if iskeydown( VK_W) and iskeydown( VK_I) and iskeydown( VK_N) then
begin
2018-05-20 11:16:50 +02:00
usedcheats: = true ;
2018-05-15 01:43:19 +02:00
if target< > nil then
target. explode; //blow up target
exit;
end ;
2017-11-02 21:01:40 +01:00
if keventtype= 0 then
begin
ct: = GetTickCount64;
2018-05-15 01:43:19 +02:00
2017-11-02 21:01:40 +01:00
if key= vk_space then
begin
if reloading< > 0 then exit;
if ct< lastshot+ 1 0 0 then exit; //rate limit the amount of bullets
x: = false ;
for i: = 0 to 4 do
if bullets[ i] = nil then
begin
//create a bullet
2017-11-07 02:42:53 +01:00
bullets[ i] : = tbullet. create( player) ;
2017-11-02 21:01:40 +01:00
bullets[ i] . x: = player. x;
bullets[ i] . y: = player. y;
bullets[ i] . rotation: = player. rotation;
x: = true ;
inc( shotsfired) ;
lastshot: = ct;
status. text : = format( 'Ammo till reload:' #13 #10 '%d' , [ 5 - shotsfired] ) ;
if shotsfired= 5 then //this ends up being extremely shitty giving the player hope he can win by timning it right. (not gonna happen lol)
begin
reloading: = ct;
if target< > nil then
begin
reloadingtargetstarthp: = target. health;
target. shielded: = true ;
end ;
status. text : = '<RELOADING>' ;
shotsfired: = 0 ;
// showmessage('reloading');
end ;
break;
end ;
end
else
begin
case key of
VK_LEFT, VK_A: if RotateDirection> = 0 then rotatedirection: = - 0.1 ;
VK_RIGHT, VK_D: if RotateDirection< = 0 then rotatedirection: = + 0.1 ;
2018-05-15 01:43:19 +02:00
2017-11-02 21:01:40 +01:00
end ;
end ;
end
else
begin
case key of
VK_LEFT, VK_A: if RotateDirection< 0 then rotatedirection: = 0 ;
VK_RIGHT, VK_D: if RotateDirection> 0 then rotatedirection: = 0 ;
end ;
end ;
result : = false ;
end ;
procedure TGame1. render;
var i: integer ;
begin
player. render;
if target< > nil then
target. render;
for i: = 0 to 4 do
if bullets[ i] < > nil then
bullets[ i] . render;
if info< > nil then
info. render
else
begin
if infobutton< > nil then
infobutton. render;
end ;
status. render;
end ;
procedure tgame1. gametick( currentTime: qword; diff: integer ) ;
2018-12-08 00:05:26 +01:00
var
i: integer ;
2017-11-02 21:01:40 +01:00
begin
2018-05-20 11:16:50 +02:00
if ticking= false then exit;
2017-11-02 21:01:40 +01:00
if reloading< > 0 then
begin
if target< > nil then
target. health: = reloadingtargetstarthp+ trunc( ( currenttime- reloading) / 2 0 0 0 * ( 1 0 0 - reloadingtargetstarthp) ) ;
//check if done reloading
if currenttime> ( reloading+ 2 0 0 0 ) then
begin
status. text : = 'Ammo till reload:' #13 #10 '5' ;
reloading: = 0 ;
target. health: = 1 0 0 ;
target. shielded: = false ;
end ;
end ;
if player< > nil then
begin
player. rotation: = player. rotation+ rotatedirection* diff;
end ;
for i: = 0 to 4 do
if bullets[ i] < > nil then
begin
bullets[ i] . travel( diff) ;
2018-05-15 01:43:19 +02:00
if ( target< > nil ) and ( target. isdead= false ) and bullets[ i] . checkCollision( target) then //perhaps use a vector based on old x,y and new x,y
2017-11-02 21:01:40 +01:00
begin
if reloading= 0 then
target. health: = target. health- 2 4 ;
if target. health< = 0 then
2018-05-15 01:43:19 +02:00
target. explode;
2017-11-02 21:01:40 +01:00
freeandnil( bullets[ i] ) ;
end ;
if ( bullets[ i] < > nil ) and ( ( bullets[ i] . x> 1 ) or ( bullets[ i] . y> 1 ) or ( bullets[ i] . x< - 1 ) or ( bullets[ i] . y< - 1 ) ) then
begin
freeandnil( bullets[ i] ) ;
2018-05-15 01:43:19 +02:00
//exit;
2017-11-02 21:01:40 +01:00
end ;
end ;
2018-05-15 01:43:19 +02:00
if ( target< > nil ) and target. isdead and ( target. blownup) then
begin
freeandnil( target) ;
2018-05-20 11:16:50 +02:00
ticking: = false ;
2018-05-15 01:43:19 +02:00
showmessage( 'well done' ) ;
2018-12-08 00:05:26 +01:00
with tregistry. create do
begin
if OpenKey( '\Software\Cheat Engine\GTutorial' , true ) then
WriteBool( 'This does not count as a solution for tutorial 1' , True ) ;
free;
end ;
2018-05-15 01:43:19 +02:00
gamewon( ) ;
end ;
2017-11-02 21:01:40 +01:00
end ;
function TGame1. infoPopup( sender: tobject) : boolean ;
begin
if info< > nil then exit( false ) ;
info: = TGUITextObject. create( fpanel) ;
info. firstTextBecomesMinWidth: = true ;
info. width: = 0.8 ;
info. height: = 0.8 ;
info. x: = 0 ;
info. y: = 0 ;
info. rotationpoint. x: = 0 ;
info. rotationpoint. y: = 0 ;
info. color: = clBlack;
info. bcolor: = clWhite;
info. backgroundAlpha: = 1 9 0 ;
info. font. Size: = 9 ;
info. text : = 'Step 1:' #13 #10 'Every 5 shots you have to reload,' #13 #10 'after which the target will heal' #13 #10 'Try to find a way to destroy the target' #13 #10 ' ' #13 #10 '(Click to hide)' ;
info. OnClick: = @ HideInfo;
result : = true ;
end ;
function TGame1. HideInfo( sender: tobject) : boolean ;
begin
freeandnil( info) ;
result : = true ;
end ;
destructor TGame1. destroy;
begin
if player< > nil then
freeandnil( player) ;
if target< > nil then
freeandnil( target) ;
if status< > nil then
freeandnil( status) ;
if infobutton< > nil then
freeandnil( infobutton) ;
if info< > nil then
freeandnil( info) ;
inherited destroy;
end ;
constructor TGame1. create( p: TGamePanel) ;
begin
fpanel: = p;
player: = tplayer. create;
player. x: = 0 ;
player. y: = 0.8 ;
target: = TTarget. create;
target. x: = 0 ;
target. y: = - 0.8 ;
target. health: = 1 0 0 ;
status: = TGUITextObject. create;
status. firstTextBecomesMinWidth: = true ;
status. font. Size: = 7 8 ;
status. width: = 0.4 ;
status. height: = 0.3 ;
status. x: = 1 - status. width;
status. y: = 1 - status. height;
status. textalignment: = taCenter;
status. firstTextBecomesMinWidth: = true ;
status. color: = clred;
status. bcolor: = clgreen;
status. text : = 'Ammo till reload:' #13 #10 '5' ;
infobutton: = TStaticGUIObject. create( p, 'infobutton.png' , 0.1 , 0.1 ) ;
infobutton. rotationpoint. y: = 1 ; //so the bottom will be the y pos
infobutton. x: = - 1 ;
infobutton. y: = 1 ;
infobutton. OnClick: = @ infopopup;
infopopup( infobutton) ;
2018-05-20 11:16:50 +02:00
ticking: = true ; //start
2017-11-02 21:01:40 +01:00
end ;
end .