Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
6e96b1dfd6
17
README.md
17
README.md
@ -7,5 +7,18 @@ Skład zespołu:
|
||||
- Michał Czekański
|
||||
- Marcin Kostrzewski
|
||||
|
||||
Poruszanie się: *WASD*
|
||||
Podnoszenie obiektów: *SPACJA*
|
||||
## Wymagania
|
||||
```
|
||||
Python 3.x
|
||||
pygame: 1.9.x
|
||||
```
|
||||
## Uruchomienie
|
||||
```
|
||||
$ python Run.py
|
||||
```
|
||||
## Konfiguracja
|
||||
Plik z konfiguracją znajduje w ```data/config/mainConfig.json```.
|
||||
|
||||
## Sterowanie
|
||||
* Poruszanie się: *WASD*
|
||||
* Interakcja: *SPACJA*
|
BIN
data/images/entities/firepit.png
Normal file
BIN
data/images/entities/firepit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
BIN
data/images/entities/gravestone.png
Normal file
BIN
data/images/entities/gravestone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 164 KiB |
BIN
data/images/entities/purewater.png
Normal file
BIN
data/images/entities/purewater.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
BIN
data/images/entities/tree.png
Normal file
BIN
data/images/entities/tree.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@ -74,5 +74,416 @@
|
||||
"thirst": 0,
|
||||
"hunger": -25
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "firepit",
|
||||
"position" : {
|
||||
"x": 10,
|
||||
"y": 7
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 10,
|
||||
"stamina": 15,
|
||||
"thirst": 0,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 5
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 6
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 7
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 7
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 8
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "purewater",
|
||||
"position" : {
|
||||
"x": 1,
|
||||
"y": 8
|
||||
},
|
||||
"isPickupable": false,
|
||||
"effect" : {
|
||||
"hp": 2,
|
||||
"stamina": 2,
|
||||
"thirst": -40,
|
||||
"hunger": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "rock",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 4
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "rock",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 5
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "rock",
|
||||
"position" : {
|
||||
"x": 4,
|
||||
"y": 5
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 3
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 2,
|
||||
"y": 4
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 2
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 3
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 13,
|
||||
"y": 8
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 13,
|
||||
"y": 7
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 12,
|
||||
"y": 17
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 12,
|
||||
"y": 14
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 13,
|
||||
"y": 14
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 15,
|
||||
"y": 14
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 13,
|
||||
"y": 15
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 13,
|
||||
"y": 16
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 10,
|
||||
"y": 16
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 10,
|
||||
"y": 17
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 11,
|
||||
"y": 17
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "cranberry",
|
||||
"position" : {
|
||||
"x": 12,
|
||||
"y": 15
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : 0,
|
||||
"stamina" : 5,
|
||||
"thirst" : -2,
|
||||
"hunger" : -10
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "berry",
|
||||
"position" : {
|
||||
"x": 11,
|
||||
"y": 16
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : -10,
|
||||
"stamina" : 5,
|
||||
"thirst" : 0,
|
||||
"hunger" : -20
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "cranberry",
|
||||
"position" : {
|
||||
"x": 5,
|
||||
"y": 12
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : 0,
|
||||
"stamina" : 5,
|
||||
"thirst" : -2,
|
||||
"hunger" : -10
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "cranberry",
|
||||
"position" : {
|
||||
"x": 5,
|
||||
"y": 13
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : 0,
|
||||
"stamina" : 5,
|
||||
"thirst" : -2,
|
||||
"hunger" : -10
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 6,
|
||||
"y": 13
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "rock",
|
||||
"position" : {
|
||||
"x": 7,
|
||||
"y": 15
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 6,
|
||||
"y": 15
|
||||
},
|
||||
"isPickupable" : false
|
||||
}
|
||||
,
|
||||
{
|
||||
"name" : "tree",
|
||||
"position" : {
|
||||
"x": 6,
|
||||
"y": 14
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "rabbit",
|
||||
"position" : {
|
||||
"x": 17,
|
||||
"y": 6
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp": 30,
|
||||
"stamina": -5,
|
||||
"thirst": -5,
|
||||
"hunger": -40
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "rabbit",
|
||||
"position" : {
|
||||
"x": 3,
|
||||
"y": 14
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp": 30,
|
||||
"stamina": -5,
|
||||
"thirst": -5,
|
||||
"hunger": -40
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "berry",
|
||||
"position" : {
|
||||
"x": 5,
|
||||
"y": 16
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : -10,
|
||||
"stamina" : 5,
|
||||
"thirst" : 0,
|
||||
"hunger" : -20
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "berry",
|
||||
"position" : {
|
||||
"x": 7,
|
||||
"y": 13
|
||||
},
|
||||
"isPickupable" : true,
|
||||
"effect" : {
|
||||
"hp" : -10,
|
||||
"stamina" : 5,
|
||||
"thirst" : 0,
|
||||
"hunger" : -20
|
||||
}
|
||||
},
|
||||
{
|
||||
"name" : "bush",
|
||||
"position" : {
|
||||
"x": 7,
|
||||
"y": 5
|
||||
},
|
||||
"isPickupable" : false
|
||||
},
|
||||
{
|
||||
"name" : "bush",
|
||||
"position" : {
|
||||
"x": 10,
|
||||
"y": 15
|
||||
},
|
||||
"isPickupable" : false
|
||||
}
|
||||
]
|
@ -1,3 +0,0 @@
|
||||
from game.Game import Game
|
||||
|
||||
game = Game()
|
@ -1,31 +0,0 @@
|
||||
from src.entities.Entity import Entity
|
||||
|
||||
|
||||
class Collidable(Entity):
|
||||
|
||||
def __init__(self, texture, pos, id):
|
||||
super().__init__(texture, pos, id)
|
||||
|
||||
def check_for_collision(self, x_pos, y_pos):
|
||||
if self.pos[0] == x_pos:
|
||||
if self.pos[1] == y_pos:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
#col = Collidable(1, 1, 1)
|
||||
|
||||
|
||||
"""
|
||||
def interact_with_hp(self, hp, Statistics):
|
||||
Statistics.set_hp(hp)
|
||||
|
||||
def interact_with_hunger(self, hunger, Statistics):
|
||||
Statistics.set_hunger(hunger)
|
||||
|
||||
def interact_with_thirst(self, thirst, Statistics):
|
||||
Statistics.set_thirst(thirst)
|
||||
|
||||
def interact_with_stamina(self, stamina, Statistics):
|
||||
Statistics.set_stamina(stamina)"""
|
@ -2,23 +2,13 @@ from src.entities.Entity import Entity
|
||||
|
||||
|
||||
class Interactable(Entity):
|
||||
def __init__(self, texture, size, pos, Statistics):
|
||||
super().__init__(texture, size, pos)
|
||||
self.Statistics = Statistics
|
||||
|
||||
def __init__(self, texture, pos, id):
|
||||
super().__init__(texture, pos, id)
|
||||
|
||||
@staticmethod
|
||||
def interact_with_hp(hp, Statistics):
|
||||
Statistics.set_hp(hp)
|
||||
|
||||
@staticmethod
|
||||
def interact_with_hunger(hunger, Statistics):
|
||||
Statistics.set_hunger(hunger)
|
||||
|
||||
@staticmethod
|
||||
def interact_with_thirst(thirst, Statistics):
|
||||
Statistics.set_thirst(thirst)
|
||||
|
||||
@staticmethod
|
||||
def interact_with_stamina(stamina, Statistics):
|
||||
Statistics.set_stamina(stamina)
|
||||
def on_interaction(self, Player):
|
||||
Player.statistics.set_hp(self.Statistics.hp)
|
||||
Player.statistics.set_stamina(self.Statistics.stamina)
|
||||
Player.statistics.set_thirst(self.Statistics.thirst)
|
||||
Player.statistics.set_hunger(self.Statistics.hunger)
|
||||
|
||||
|
@ -1,16 +1,8 @@
|
||||
from src.entities import Statistics, Player
|
||||
from src.entities.Interactable import Interactable
|
||||
|
||||
|
||||
class Pickupable(Interactable):
|
||||
def __init__(self, texture, size, pos, Statistics):
|
||||
super().__init__(texture, size, pos)
|
||||
super().__init__(texture, size, pos, Statistics)
|
||||
self.is_pickupable = True
|
||||
self.Statistics = Statistics
|
||||
|
||||
def on_pickup(self, Player):
|
||||
Player.statistics.set_hp(self.Statistics.hp)
|
||||
Player.statistics.set_stamina(self.Statistics.stamina)
|
||||
Player.statistics.set_thirst(self.Statistics.thirst)
|
||||
Player.statistics.set_hunger(self.Statistics.hunger)
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from enum import Enum
|
||||
import random
|
||||
|
||||
from src.entities.Entity import Entity
|
||||
from src.entities.Statistics import Statistics
|
||||
@ -6,8 +7,6 @@ import pygame
|
||||
|
||||
|
||||
class Player(Entity):
|
||||
statistics: Statistics
|
||||
|
||||
def __init__(self, spawnpoint, size):
|
||||
super().__init__("player.png", size, (spawnpoint[0] * size, spawnpoint[1] * size))
|
||||
# Where the player is facing, 0 - north, 1
|
||||
@ -15,12 +14,21 @@ class Player(Entity):
|
||||
self.statistics = Statistics(100, 0, 0, 100)
|
||||
# How many steps has the player taken through its lifetime
|
||||
self.movePoints = 0
|
||||
# Tracks how much time has passed since the player is alive
|
||||
self.timer = pygame.time.Clock()
|
||||
self.timeAlive = 1
|
||||
# Used to determine fatigue
|
||||
self.fatigueTimeout = 0
|
||||
|
||||
self.alive = True
|
||||
# If a player dies, the death reason is stored here
|
||||
self.deathReason = None
|
||||
# Move in a desired direction
|
||||
def move(self, rotation):
|
||||
self.movePoints += 1
|
||||
# Player gets tired aswell!
|
||||
self.applyFatigue()
|
||||
# You can only move if you have enough stamina
|
||||
if self.statistics.stamina > 1:
|
||||
self.applyWalkingFatigue()
|
||||
if rotation.value == Rotations.NORTH.value:
|
||||
self.rect.y -= self.rect.w
|
||||
elif rotation.value == Rotations.EAST.value:
|
||||
@ -30,16 +38,27 @@ class Player(Entity):
|
||||
elif rotation.value == Rotations.WEST.value:
|
||||
self.rect.x -= self.rect.w
|
||||
|
||||
def applyFatigue(self):
|
||||
def applyWalkingFatigue(self):
|
||||
# looses hunger every 10 steps taken
|
||||
if self.movePoints % 10 == 0:
|
||||
self.statistics.set_hunger(10)
|
||||
self.statistics.set_hunger(5)
|
||||
# gets more thirsty every 5 steps
|
||||
if self.movePoints % 5 == 0:
|
||||
self.statistics.set_thirst(10)
|
||||
self.statistics.set_thirst(6)
|
||||
# gets tired every step
|
||||
self.statistics.set_stamina(-2)
|
||||
|
||||
def applyTimeFatigue(self, tickTime):
|
||||
self.fatigueTimeout += tickTime
|
||||
if self.fatigueTimeout >= 700:
|
||||
self.statistics.set_thirst(5)
|
||||
self.statistics.set_hunger(3)
|
||||
# A player can randomly regenerate stamina
|
||||
if random.randrange(5) == 0:
|
||||
self.statistics.set_stamina(2)
|
||||
self.fatigueTimeout = 0
|
||||
|
||||
|
||||
def getFacingCoord(self):
|
||||
if self.rotation == Rotations.NORTH:
|
||||
return self.rect.x, self.rect.y - (self.rect.h)
|
||||
@ -71,6 +90,31 @@ class Player(Entity):
|
||||
self.image = pygame.transform.rotate(self.image, ((self.rotation.value - rotation.value) * 90))
|
||||
self.rotation = rotation
|
||||
|
||||
# Updates self.alive if any of the statistic reaches critical value
|
||||
def determineLife(self):
|
||||
if self.statistics.hunger == 100:
|
||||
self.alive = False
|
||||
self.deathReason = StatisticNames.HUNGER
|
||||
elif self.statistics.thirst == 100:
|
||||
self.alive = False
|
||||
self.deathReason = StatisticNames.THIRST
|
||||
elif self.statistics.hp == 0:
|
||||
self.alive = False
|
||||
self.deathReason = StatisticNames.HP
|
||||
|
||||
# Change texture after dying
|
||||
if not self.alive:
|
||||
self.image, null = self.getTexture("gravestone.png", self.rect.h)
|
||||
|
||||
# Called every frame
|
||||
def update(self):
|
||||
if self.alive:
|
||||
self.timeAlive += self.timer.get_time()
|
||||
# Player gets tired every once in a while
|
||||
self.applyTimeFatigue(self.timer.get_time())
|
||||
self.timer.tick()
|
||||
self.determineLife()
|
||||
|
||||
|
||||
class Rotations(Enum):
|
||||
NORTH = 0
|
||||
|
@ -1,5 +1,6 @@
|
||||
import pygame
|
||||
|
||||
from src.entities.Interactable import Interactable
|
||||
from src.entities.Pickupable import Pickupable
|
||||
from src.entities.Player import Rotations
|
||||
|
||||
@ -39,11 +40,19 @@ class EventManager:
|
||||
def handlePlayerControls(self, keys):
|
||||
# Key names are temporary
|
||||
# TODO: Load key bindings from JSON
|
||||
|
||||
if self.player.alive:
|
||||
# Picking up items
|
||||
if keys[pygame.K_SPACE]:
|
||||
object = self.game.map.getEntityOnCoord(self.player.getFacingCoord())
|
||||
# Picked up item gets removed from the map
|
||||
if type(object) is Pickupable:
|
||||
object.on_pickup(self.player)
|
||||
object.on_interaction(self.player)
|
||||
self.game.map.removeSpriteFromMap(object)
|
||||
elif type(object) is Interactable:
|
||||
object.on_interaction(self.player)
|
||||
|
||||
# Movement
|
||||
if keys[pygame.K_w]:
|
||||
self.player.rotate(Rotations.NORTH)
|
||||
if not self.game.map.collision(self.player.rect.x, self.player.rect.y - self.player.rect.w):
|
||||
|
@ -3,13 +3,11 @@ import json
|
||||
from pathlib import Path
|
||||
from os import path
|
||||
|
||||
from game.EventManager import EventManager
|
||||
from game.Screen import Screen
|
||||
from game.Map import Map
|
||||
from src.game.EventManager import EventManager
|
||||
from src.game.Screen import Screen
|
||||
from src.game.Map import Map
|
||||
|
||||
from src.entities.Pickupable import Pickupable
|
||||
from src.entities.Player import Player
|
||||
from src.entities.Statistics import Statistics
|
||||
from src.game.Timer import Timer
|
||||
|
||||
|
||||
@ -61,6 +59,7 @@ class Game:
|
||||
while self.running:
|
||||
# Update ingame clock
|
||||
self.ingameTimer.updateTime(self.pgTimer.tick())
|
||||
self.spritesList.update()
|
||||
self.eventManager.handleEvents()
|
||||
self.spritesList.draw(self.screen.pygameScreen)
|
||||
pygame.display.flip()
|
||||
|
@ -1,6 +1,8 @@
|
||||
import json
|
||||
|
||||
import pygame
|
||||
|
||||
from src.entities.Interactable import Interactable
|
||||
from src.game.TerrainTile import TerrainTile
|
||||
from src.game.Screen import Locations
|
||||
|
||||
@ -41,6 +43,7 @@ class Map:
|
||||
entityListJson = json.loads(file.read())
|
||||
for entity in entityListJson:
|
||||
try:
|
||||
# Creates a pickupable object
|
||||
if entity["isPickupable"]:
|
||||
actualEntities.append(Pickupable(entity["name"] + ".png",
|
||||
self.tileSize,
|
||||
@ -49,6 +52,17 @@ class Map:
|
||||
entity["effect"]["hunger"],
|
||||
entity["effect"]["thirst"],
|
||||
entity["effect"]["stamina"])))
|
||||
# Creates an interactable object
|
||||
elif "effect" in entity:
|
||||
actualEntities.append(Interactable(entity["name"] + ".png",
|
||||
self.tileSize,
|
||||
(entity["position"]["x"] * self.tileSize,
|
||||
entity["position"]["y"] * self.tileSize),
|
||||
Statistics(entity["effect"]["hp"],
|
||||
entity["effect"]["hunger"],
|
||||
entity["effect"]["thirst"],
|
||||
entity["effect"]["stamina"])))
|
||||
# Creates plain entity
|
||||
else:
|
||||
actualEntities.append(Entity(entity["name"] + ".png",
|
||||
self.tileSize,
|
||||
|
@ -78,7 +78,7 @@ class Ui():
|
||||
|
||||
if self.thirstBar.value != statistics.thirst:
|
||||
self.thirstBar.updateFill(statistics.thirst)
|
||||
consoleLines.append(self.timer.getPrettyTime() + " - Stamina: " + str(statistics.thirst))
|
||||
consoleLines.append(self.timer.getPrettyTime() + " - Thirst: " + str(statistics.thirst))
|
||||
|
||||
if len(consoleLines) > 0:
|
||||
self.console.addLinesToConsoleAndScrollToDisplayThem(consoleLines)
|
||||
|
Loading…
Reference in New Issue
Block a user