#GameLogic
1 messages · Page 1 of 1 (latest)
okay sure
state:
public enum State {
WAITING, STARTING, IN_PROGRESS, BOSS_FIGHT, PAUSE, ENDING, RESETTING
}
currentLevel: current game instance level. Used to activate many other things.
locations ---> getLocations(int currentLevel):
Uses the current level number to add the locations depending on the level.
Constructor
public DungeonGame(int dungeonGameID, World world) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
state = State.RESETTING; <----------- Sets game state as resetting
players = new ArrayList<>();
spectators = new ArrayList<>();
locations = new Locations(world); <---------- Instance of locations which stores spawn locations as well as start locations etc.
currentLevel = 1; <-------- Initializes default level to 1
mythicMob = null;
new BukkitRunnable() {
@Override
public void run() {
activateDungeon();
}
}.runTaskTimer(plugin, 0, 30);
}
activateDungeon is the infinite loop that runs and decides the next thing to do in the game
public void activateDungeon() {
switch (state) {
case WAITING -> {
messagePlayers("&rThe dungeon is waiting for players!");
}
case STARTING -> {
if (players.size() >= 1) {
leader = players.get(0);
state = State.PAUSE; <-------- Sets the state to pause because players need to get teleported from the "lobby" area to the first level spawn and will wait for the leader to type /start
break;
}
}
case IN_PROGRESS -> {
generateLevel(); <----- This does the spawning for stuff for the current level. method below
}
case PAUSE -> {
generateLevel(); <----- This does the spawning for stuff for the current level. method below
titlePlayers("&2&l/dm next &rto continue!", "Waiting for &2&lleader &rto resume the dungeon!"); <---- Wait for leader to change gamestate with command
}
case ENDING -> {
messagePlayers("&rThe dungeon is ending!");
if (players.size() == 0) {
state = State.RESETTING;
break;
}
}
case RESETTING -> {
messagePlayers("&rThe dungeon is resetting!");
currentLevel = 1;
resetVariables();
addLocations(currentLevel);
state = State.WAITING;
}
}
}
This method is used to begin the dungeon the first time only.
public void start() {
state = State.STARTING;
}
This method is used to begin each level in the game.
public void ready() {
state = State.IN_PROGRESS;
}
GenerateLevel()
private void generateLevel() {
new BukkitRunnable() {
@Override
public void run() {
if (killCount >= Level.getKillGoal(currentLevel)) {
spawnBoss();
cancel(); <----- level goal reached
}
if (spawnedCount > 40)
return; <----- Ignore but this is just to prevent overspawn
for (int i = 0; i < 10; i++) {
Location location = locations.getRandomLocation();<--- spawn logic, ignore
mythicMob.spawn(BukkitAdapter.adapt(location), 1); <--- spawn logic, ignore
}
}
}.runTaskTimer(plugin, 10, 10);
}
Not saying it's not working or it is but:
What I want to accomplish is that before the first player joins all the firstlevel currentLevel = 1 locations are loaded. The player then gets teleported to the waiting area
Once the player does /start -> He gets teleported to the start location of the first level. Level plays out, etc
After the level finishes:
Player is teleported to the location of level2 which is only added when addLocations() -> Uses the current level is called.
Gamestate is waiting until player types /ready
When he does, generate level starts to create and then repeats itself
@fallen vigil @muted echo noti
ok
I hope i explained it correctly, I can provide the full code but I removed all the stuff in the middle to make it as easily readable as possible
looks like a standard state machine
Ok so it makes sense to you? right?
so is teh goal that any player can start at any time
Start or ready?
or do you just want the dungeon to start the game regardless of how many people are in it
like whats the user experience gonna be
It can be played as 1 or more than one so yes. Start when the player wants
okay
If they want to have teammates they can. first player to join is set as the leader. that's all working
so for each group of players there is a dungeon
Yes
and each dungeon is this statemachine
Wait no this not correct
Each dungeongame can only have 1 group of players
seems to work fine
rip server xD
so the issue is that it goes to pause when the game starts?
Nono the issue is that when /start is used. It should teleport you to the locationof the level and you need to type /ready to begin the level
first red dot is the command which calls this
public void start() {
state = State.STARTING;
}
Second and third (ignore third )
private void generateLevel() {
new BukkitRunnable() {
@Override
public void run() {
if (killCount >= Level.getKillGoal(currentLevel)) {
spawnBoss();
cancel(); <----- level goal reached
}
if (spawnedCount > 40)
return; <----- Ignore but this is just to prevent overspawn
for (int i = 0; i < 10; i++) {
Location location = locations.getRandomLocation();<--- spawn logic, ignore
mythicMob.spawn(BukkitAdapter.adapt(location), 1); <--- spawn logic, ignore
}
}
}.runTaskTimer(plugin, 10, 10);
}
when is generate called
Here is what I think I did wrong. It's being called both in inprogress and pause
have you even made a state diagram?
Wait I think just talking to you gave me the solution because of the questions you asked
Ummm
its a map of all your states with arrows between them for each transition
then you can visually see what your state will be and how to get to another state
I assume I make that manually like a uml unless intelliJ
yes its an uml state diagram, but i dont think intellij can make those
since its more removed from teh code as it doesnt define the implementation, but just the logic
Alright let me think about it
What tool did you use for that
google images
Oh lmao
Perfect, will do right away. be bask in a bit
also there are probably better ways to implement the state machine, especially if it is going to be big
but one thing at a time
I would like to read or see more stuff about that. would be really useful
Yeah for sure let me draw this up
Wait do I think of this as what I currently have or what I want?
what you want
I mean if you did it right they should be the same
so just design it to how you think the game should work
idk what you want xD
lmao
this just means that there is no way to go to waiting, unless you create a new dungeon
if that's is what you want then its fine
if a state is instant, there might not even be a reason for it
Let me change the diagram then 1 serc
like starting, from what I saw its like a transition between waiting and paused
well as a general rule of thumb, if a state is instant like that, it probably shouldnt be a state at all
since it will only occur in the transition between waiting and pause, and its instant
Changed it up
That's how I want it
/start only once and /ready each level
You're right tho prob can remove starting and make /start still take you to pause
yes
Alright baby steps here but I'm understanding everything
switch (state) {
case WAITING -> {
}
case PAUSE -> {
}
case IN_PROGRESS -> {
}
case BOSS_FIGHT -> {
}
case RESETTING -> {
}
}
``` Alright rewriting the method to start fresh
So according to what I'm doing. If i need the locations for the upcoming level I would need to add them after islastlevel since before the first level they are already loaded from the constructor
public void activateDungeon1() {
//Generate switch logic with no code inside of them
switch (state) {
case WAITING -> {
messagePlayers("&rThe dungeon is waiting for players!");
setWorldBorder();
}
case PAUSE -> {
setWorldBorder();
titlePlayers("&2&l/dm ready &rto continue!", "Waiting for &2&lleader &rto resume the dungeon!");
}
case IN_PROGRESS -> {
generateLevel();
setWorldBorder();
}
case BOSS_FIGHT -> {
}
case ENDING -> {
if (players.size() != 0) {
getPlayers().forEach(dungeonPlayer -> {
dungeonPlayer.getPlayer().setGameMode(GameMode.SURVIVAL);
dungeonPlayer.getPlayer().teleport(Bukkit.getWorld("spawn").getSpawnLocation());
removePlayer(dungeonPlayer.getPlayer());
TitleManager.sendTitleWithPrefix(dungeonPlayer.getPlayer(), "Resetting, You have been teleported to spawn!");
});
}
if (spectators.size() != 0) {
getSpectators().forEach(dungeonSpectator -> {
dungeonSpectator.getPlayer().setGameMode(GameMode.SURVIVAL);
dungeonSpectator.getPlayer().teleport(Bukkit.getWorld("spawn").getSpawnLocation());
TitleManager.sendTitleWithPrefix(dungeonSpectator.getPlayer(), "Resetting, You have been teleported to spawn!");
removeSpectator(dungeonSpectator.getPlayer());
});
}
}
case RESETTING -> {
leader = null;
currentLevel = 1;
resetVariables();
addLocations(currentLevel);
state = State.WAITING;
}
}
}
``` polished that a bunch
yeah this looks nice
and then I assume most state changes are called by like commands or whatever
like waiting -> paused by /start
Talking with someone always helps especially people that ask the right questions and suggest stuff
true