HeroEngine Forums
Welcome, Guest. Please login or Register for HeroCloud Account.

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - Jrome90

Pages: [1] 2
1
General Discussion / Simplify the creation of DOM data
« on: Nov 20, 16, 08:18:46 PM »
I never was a fan of the DOM editor or the Command Line Interface to make changes to the DOM. I made a program to automate the process of the creation of DOM data for Enums, Classes, and Fields. I call it  "Auto_CLI".

This program looks for two JSON files. One for the client and another for the server(in that order).
run.bat:
Code: [Select]
%CD%\CLI_Automation Example_Client.json Example_Server.json
If you have nothing to add to the server or client you can leave one of the files empty with:
Code: [Select]
{
}
Below are examples showing all properties and DOM objects supported on both the server and client:
Both The field: minimumField and the class: MinimumClass are examples of what the minimum requirements for a field, and class are.
Anything that is not defined in the JSON* object has the same default value as the Dom Editor.
Code: [Select]
{
  "Fields":
  {
    "someField":
    {
      "description": "enter a description",
      "field type": "enum ENUM_EX",
      "reflect to ghost": false,
      "write strategy": "lazy",
      "watching script": "None",
      "private": true,
      "distribution package": "game"
    },
    "minimumField":
    {
      "description": "enter description",
      "field type": "integer",
      "distribution package": "game"
    }
  },

  "Classes": {
    "SomeClass": {
      "archetype": "Data",
      "description": "Enter A description",
      "distribution package": "Game",
      "parent classes": [ "MinimumClass" ],
      "fields": [ "someField", "minimumField" ]

    },
    "MinimumClass": {
      "archetype": "Data",
      "description": "Enter A description",
      "distribution package": "Game"
    }
  },

  "Enumerations":{
    "ENUM_EX": {
      "description": "Enter A description",
      "distribution package": "game",
      "enum values": [ "ENUM1", "ENUM2", "ENUM3" ]
    }
  }
}
Example_Server.json
Code: [Select]
{
  "Fields":
  {
    "someField":
    {
      "description": "enter a description",
      "field type": "enum ENUM_EX",
      "reflect to ghost": false,
      "write strategy": "never",
      "watching script": "None",
      "private": true,
      "distribution package": "game",
      // Replication properties are server side only
      "discrete": true,
      "change callback": true,
      "destination field": "someField",
      "destination field client": "someField",
      "reverse replicate": true,
      "reference adjust": false,
      "initial priority": 123,
      "delta priority": 123,
      "lifetime": 1234,
      "distance factor": 100
    },
    "minimumField":
    {
      "description": "enter description",
      "field type": "integer",
      "distribution package": "game"
    }
  },

  "Classes": {
    "SomeClass": {
      "archetype": "Data",
      "description": "Enter A description",
      "distribution package": "Game",
      "destination class server": "SomeClass",  // Replication properties are server side only
      "destination class client": "SomeClass", // Replication properties are server side only
      "parent classes": [ "MinimumClass"],
      "fields": [ "someField", "minimumField" ],
      // Replication properties are server side only
      "replicated fields": [ "someField" ],
      "initial set fields": [ "someField" ]
    },
    "MinimumClass": {
      "archetype": "Data",
      "description": "Enter A description",
      "distribution package": "Game"
    }
  },

  "Enumerations":{
    "ENUM_EX": {
      "description": "Enter A description",
      "distribution package": "game",
      "enum values": [ "ENUM1", "ENUM2", "ENUM3" ]
    }
  }
}


Most errors are displayed and then stop the execution of the program. Errors that are caused by attempting to create a definition that already exists are ignored.


Limitations:
*This program will not work with any reference worlds.
*Requires the console to be visible .
*It may take some time before the program finds the console. It's recommended to close the dom editors to speed up the search.
*It may not work very well, or at all if your console is spammed with messages.
*Doesn't support creation of association DOM definitions.

Benefits
*Use the JSON format that this program uses to share DOM definitions with others.
*A class or field is fast and easy to create
Code: [Select]
{
  "Fields": {
    "field": {
      "description": "enter description",
      "field type": "integer",
      "distribution package": "game"
    }
  },

  "Classes": {
    "class": {
      "archetype": "Data",
      "description": "Enter A description",
      "distribution package": "Game"
    }
  }
}
*A way to manually Backup the DOM definitions using the JSON format.
*Includes templates for the DOM definitions for spec creation.
----------------
To use
Download the zip file here
Create one JSON file for the server and one for the client.
Edit the .bat file to change the arguments to the names of the files you want to use
Have the HeroBlade open with the console visible.
run the .bat file and wait until it's done or an error has occurred. If an error occurs make the corrections and run it again.

Please let me know if you encounter any bugs.
-------------------------------------------------------------

2
I wanted to share this spreadsheet that I thought could be useful.
It contains the following data for both client and server side:
  • Class ID
  • Class Name
  • Archetype
  • Package
  • Description
  • Server Destination
  • Client Destination

Why might this be useful?
Because it's much better than looking through the DOM editor, or QCD and looking through the Console for a class ID.
And from what I could tell the Class IDs are the same across worlds. So You can use "|or \ scd for fast lookup.

For those that want to know how long this took to make
Around Five minutes (Computers are fast)

https://docs.google.com/spreadsheets/d/1vEJcpTaUmoSgZvd657FMwzuplugUSP5tXWxNqQjHbP0/edit?usp=sharing






3
General Discussion / Create New Class dialog bug
« on: Aug 12, 15, 03:36:00 AM »
Start typing in the field name and sometimes this happens

The only way to select a field is to use the arrow keys

Once you hit enter to choose the field:

I can only get these things to happen for the first field that is added

4
For quite some time, the Right-Click Context menu for "Stateful Objects" hasn't worked.
Clicking on "OPEN", or  "Edit State" did absolutely nothing.


To Fix this:
Open up the script '_statefulObjectClassMethods"
Under "shared function DoContextMenuItem"
At line 144*

Change
Code: [Select]
  if not ( IsPlayerUsingEditClient( player ) and _GetAuthorizationValue( player, "__IsAllowedToEditAreas" ))
To
Code: [Select]
  if ( IsPlayerUsingEditClient( player ) and _GetAuthorizationValue( player, "__IsAllowedToEditAreas" ))
Compile, and Submit

*Assuming that there have been no changes to this script
Because this is a Clean Engine script, this fix will be overridden if there is an update.

5
Quite sometime ago I created a simple to use tool that allows you to easily place Trees. Even though the name is the "Asset placement tool" it currently is limited to only speed trees. In the near future I will change it to be able to use speed trees, and HGM format models as well.

Demonstration video by Dwight: http://www.youtube.com/watch?v=M6rFnxsOKOA

Using this tool you can mass-place randomly scaled, and rotated trees. I do not recommend doing that though. Please just place a tree one by one.

Each asset (Tree) has a spec that enables you to set the random rotation range for each axis, and a range for the scale via the "Asset Spec Editor GUI"

Each asset is then manually added to a "Preset Spec" that is used to determine what assets are available to be used.
For example: You can add foliage that is only in a desert to a preset spec that is named "Desert foliage".
When that Preset Spec is selected, only those assets can be placed.

Adding this tool

Because this tool has many fields, and quite a few classes it would take a long time for somebody to manually add all of them. To prevent this, I created a simple python script (Also compiled to an EXE via PyInstaller)that will enter the CLI commands to create all the required fields and classes.

You must download this zip file: https://dl.dropboxusercontent.com/u/85478021/Implement%20AssetPlacementTool.zip

The contents of the zip file:

PlacementToolGrid File: Has the required HGM models and textures for the editor. Created By Dwight
apttoolgui.xml
3 Docx files containing required HSL code to be used
AutoCLICommands.exe (Python code compiled to .exe via PyInstaller) Size is  around 5mb because all required Dlls are packaged into the single Exe
AutoCLICommands.py (Python 2.7)
Jerome_Tool.dds -> GUI texture sheet for the tool. Created By Dwight
ParseTest.txt -> CLI commands that are read from this file.

READ_ME_FIRST.txt -> Instructions to add the tool

Quote from:  READ_ME_FIRST.txt
#######################################################
If you haven't Setup your world to be able to use the spec system
You must do that first. See: http://hewiki.heroengine.com/wiki/Spec_system

Under: Creating a game specific implementation of SpecOracleUtils
#######################################################

1. In the repository, create a folder in your HE Root Directory Named: "PlacementToolGrid"
2. Place all contents of the folder "PlacementToolGrid" into that folder.
3. Add the DDS file "Jerome_Tool.dds" to the GUI folder in the repository

4. Using the script editor, create an XML file "apttoolgui" and paste the XML from the text file "apttoolgui.xml"
(Compile and submit)

5. Before doing step 6, copy the class "minMax" over to the server via the "Copy to server" button

6. Run AutoCLICommands.exe   (If you have python 2.7 installed you can view/run the python file that was used to create this exe)
Then immediately click in the CLI Entry field (As if you were to enter a CLI command)
Wait 10 seconds, then it will start to automatically enter the commands from the file "ParseText"

You must keep the CLI Entry field in focus until finished.

Unfortunately there is no way to stop the AutoCLICommands. I recommend doing a little at a bit at a time*.

* To do a little bit at a time
Paste the text from ParseTest into a temporary text file.

After copy/pasting the text into the temporary file, delete all text in the "ParseTest" file

Next, Cut(ctrl+x) a part from the the temporary file and paste it into the "ParseTest" file

Save the "ParseTest" file and Run AutoCLICommands.exe (While the commands are being executed in the CLI, Check for any errors Before and After)

Repeat the proccess until there is nothing remaining in the temporary file.

**Of course you can just run all the way though, I am pretty sure I fixed any errors I encountered When adding it to another world.

Please report any errors

***************************************
Before some scripts can be compiled, and submitted, some code may need to be commented out first.
(Such parts include remote calls, and other code due to bad design.
**************************************

7. Open the .docx file "ServerSideClassScripts" and create the scripts for the corresponding classes. (Each Script has the class name above it
 
8. Open the .docx file "ClientSideClassScripts" and create the scripts for the corresponding classes.

9. 5. Open the .docx file "AssetPlacementToolAndGui" and create the scripts for the corresponding classes.

10. Lastly, open the .docx file "OtherModificationsRequired", and follow the instructions

Once the above is done, and every script is compiled, you can do the following to use the tool:

To access, and create Asset Properties Specs (Required)
You can type the following into the chat panel: /heoracle open apt_assetpropertiesspecoracle

To access, and create Preset Specs (Required)
You can type the following into the chat panel: /heoracle open apt_presetspecoracle

And to use the tool, you can type the following into the CLI: call assetplacementtoolguiclassmethods open

**************************
Controls
**************************

Asset Properties Spec Editor
-------------------------------
Inside visualization area

Mouse wheel: Zoom
MMB: Pan
Alt + MMB: Rotate
Ctrl + mouse wheel: Change collision radius
----------------------------



Asset Placement tool
-----------------------------

To select an asset to use click on the name in the panel
If no assets are selected, it uses all in the preset. Otherwise, it only uses the ones selected

# of instances: determine how many are placed (Or attempting to be placed)

Numpad +/- : Change placement area radius
Enter: Place asset
Right-click: re-roll for randomness

When a single asset is selected:
Page up/down to change the selection (Or the previous/next buttons)

Has been successfully added to 2 worlds using the above process.
This tool has been tested extensively, but might still have some bugs.

Please report any issues, or questions.

Note: There may be ways to improve a lot of the code.

Enjoy

6
General Discussion / [Resolved] HSEIDemo.dll loading issue
« on: Apr 28, 13, 12:06:17 AM »
I decided to go ahead and see if I can successfully Compile, and load the HSEIDemo plugin.

After Compiling (with VS 2012 Express) I added the dll to the same location as the heroblade.exe. Is that the proper location for client plugins?

After attempting to load the plugin using:
Code: [Select]
LoadScriptPlugin("HSEIDemo.dll") I get the error:

Code: [Select]
!ERROR!System:Error loading plugin (HSEIDemo.dll): The specified procedure could not be found.
I am not sure the error is because it can't find the plugin.. Or if it just can't load it properly.

Though I'd think it is the former.

7
I created a guicontrol class" "TMP_Button"
Which has the parent class: "_GUIButton"

GUIXML for the guicontrol:
Code: [Select]
<createControlType class='TMP_Button' type=TMP_Button' description='Borderless button ' treePath='CleanEngine' name="TMP_Button">
  <position x="497" y="288"/>
  <size x="80" y="20"/>
  <_label name="text" dockMode="FILL" text="Text" displayfont="JUMBO" justification="CENTER">
    <size x="80"/>
    <defaultStatePresentation>
      <color r="1" g="1" b="1"/>
    </defaultStatePresentation>
  </_label>
</createControlType>


When I use the following:
Code: [Select]
 
button as NodeRef of Class TMP_Button = CreateNodeFromPrototype("TMP_Button")

lbl as NodeRef of Class GUILabel = FindGUIControlByName(button,"text")
println(lbl)
The println result is: 0

And if I Analyze the Button:
Analyze> Control + Children

The children aren't there.

Console:
Code: [Select]
16:39:33: !ERROR!HeroScript::HeroMachine::ScriptError:No Node found for that node ID.
16:39:33: !ERROR!System:SCRIPT ERROR: In function GetGUICompositeScale: No Node found for that node ID.
04/23/2013 16:39:30
Call trace:
  Script GUIControlClassMethods line 204 me[id=1000010869 invalid]
  Script _GUIAnalysisDialogForControlsClassMethods line 129 me[1000016752]
  Script _GUIAnalysisDialogForControlsClassMethods line 67 me[1000016752]
starting method/function _ANALYSISWINDOWASYNCHRONOUSCONSTRUCTIONTIMER_TICK
starting me[id=1000016752 class=_GUIAnalysisDialogForControls]

The noderef of the children are invalid.
However, if I edit the control under the "Children" data field there is a node ID.
But it points to a non-existant node.

The only way I can use the button, and get the children node, is by adding the button to a gui via the gui editor.

What am I doing wrong?

Thanks

8
Scripting & Programming / [No Repro] Raycasting and props
« on: Feb 01, 13, 06:56:56 PM »
It seems that props aren't hit with raycasts.
I figured since they can have collision, raycasts could collide with them. But it isn't true.

Is that intended?

9
Is there a way to get a node's bounding box size?
I tried using GetNodeBoundingBox() but it gives me the same values for each instance of an asset. Whether they are 2x as big as others, or not.

Only the character's BoundingBox changes.

Thanks

10
General Discussion / [Resolved]Edit header GUI (Sapphire)
« on: Jan 25, 13, 01:59:55 PM »
Enhancements & Corrections
  • Added in edit header GUI to add and customize headers for spec oracles


Is the Header editor supposed to be released at a later time?

11
I missed the fact that there is
Code: (hsl) [Select]
//This causes all owned Item Containers and contained Items to be replicated
method _ReplicateAllContainers()
  containerRef as NodeRef of Class _ItemContainer
  foreach container_name in me._GetAllItemContainerNames()
    containerRef = me._GetItemContainerByName(container_name)
    containerRef._GetReplicationGroup(true)
  .
.
It is there for a reason.

Also, It seems the HSL code tags dont work anymore

12
I have been working on a tutorial. Before I continue, I would like to know if this script is readable, understandable, or just a complete mess.

While it makes sense to me. It may not for others. I dont wan't to use something that nobody can understand.
I have trouble with making my scripts clear. Atleast, I think so.

Code: (hsl) [Select]
//#define debug
remote function CreateNewGame(PlayerID as ID)
  BlackjackGame as NodeRef of Class BlackjackGame = CreateNodeFromClass("BlackjackGame")
  dealer as NodeRef of Class BlackjackDealer = CreateNodeFromClass("BlackjackDealer")
  var repGroup = BlackjackGame._GetReplicationGroup(true)
  repGroup._ReplicateNode(dealer)
  AddAssociation(BlackjackGame,"base_hard_association",dealer)
  call reply $Blackjack.RecieveNewGameID(BlackjackGame)
  while BlackjackGame.blackjackGameSeatingOrder.length != 7
    add back 0 to BlackjackGame.blackjackGameSeatingOrder
  .
  add back dealer to BlackjackGame.blackjackGameSeatingOrder
.

remote method AddPlayer(playerID as ID)
 
  playerData as NodeRef of Class BlackjackPlayer = CreateNodeFromClass("BlackjackPlayer")
 
  me.blackjackPlayers[playerID] = playerData
 
  // Set the intial balance of the new player
  // Could be done in the "BlackjackPlayer" class
  playerData.blackjackPlayerBalance = 500
  // Always has atleast one hand
  playerData.blackjackPlayerHandIndex = 1
  // Add data for both hand's wagers
  loop i from 1 to 2
    add back 0 to playerData.blackjackHandWagers
  .
  #if debug
  println("My Balance: " + playerData.blackjackPlayerBalance)
  #endif
  // Player always sits in the first empty seat found
  loop i from 1 to me.blackjackGameSeatingOrder.length
    if me.blackjackGameSeatingOrder[i] = 0
      me.blackjackGameSeatingOrder[i] = playerData
      playerData.blackjackPlayerSeat = i
      break
    .
  .
  #if debug
  println("Player: " + me.blackjackPlayers[playerID])
  #endif
  // Replicate the newly added player's data, and add their client to recieve all replication in the group
  var repGroup = me._GetReplicationGroup(false)
  repGroup._ReplicateNode(playerData)
  repGroup._AddClientDestination(playerID,None)
  #if debug
  println("Players in game: " + me.blackjackPlayers.length)
  #endif
.

remote method RemovePlayer(playerID as ID)
  if me.blackjackPlayers has playerID
   
    playerData as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
   
    loop i from 1 to me.blackjackGameSeatingOrder.length
      if me.blackjackGameSeatingOrder[i] = playerData
        remove me.blackjackGameSeatingOrder at i
        //Seat is now empty at seat i
        insert 0 to me.blackjackGameSeatingOrder at i
        break
      .
    .
    DestroyNode(playerData)
    remove playerID from me.blackjackPlayers
   
    var repGroup = me._GetReplicationGroup(true)
    repGroup._EndReplicateNode(playerData)
    repGroup._RemoveClientDestination(playerID)
   
    me.DestroyGameNode()
  .
.

method DestroyGameNode()
  if me.blackjackPlayers.length <= 0
    dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
    DestroyNode(dealer)
    DestroyNode(me)
  .
.

//Shuffle
remote Method ShuffleDeck()
  deck as List of String = GetEnumValues("Cards")

  pos as Integer
  while deck.length > 0
    pos = RandomInteger(1,deck.length)
    add back deck[pos] to me.deckOfCards
    remove deck at pos
  .

.


Method DealCardToPlayer(playerID as ID,hand as Integer)
  player as NodeRef = playerID
  card as String = me.deckOfCards[1]

  where player
    is kindof BlackjackPlayer

      me.ChangeCurrentPlayer(player)
      player.AddCardToHand(card)

      if player.CanSplitHand()
        //println("Player can Split Hand!")
      .
      if player.HandIsSoft(hand)
        println("Soft " + player.HandTotal(0)) // using 0 will tell the method we want to use the current hand being played
      .
      if player.HandIsBlackjack()
        println("Player has Blackjack!")
      .
    .
    is kindof BlackjackDealer
      me.ChangeCurrentPlayer(player)

      player.AddCardToDealerHand(card)
      if player.DealerHandIsSoft()
        println("Dealer Has Soft " + player.DealerHandTotal())
      .
      if player.blackjackDealerHand.length = 2
        println("Dealer Has two cards")
        if player.DealerHandPossibleBlackjack()
          println("Possible Blackjack!")
          me.SendPlayerEventToAllPlayers("Checking For Blackjack!",player)
          // Possible Blackjack, so start the check delay
          me.checkForBlackjackDelayTimer.fireRate = 00:00:05
          me.checkForBlackjackDelayTimer.start()
        .
      .
    .
  .
  remove me.deckOfCards at 1
.
method DealCardsToAllPlayers()
  me.blackjackCardDealDelay.stop()
  // If there still players that need to recieve cards
  if me.blackjackDealList.length > 0
    // Deal one card per second
    me.blackjackCardDealDelay.fireRate = 00:00:01
    me.blackjackCardDealDelay.start()
  else
    // all players have recieved their initial cards
    // Next, all players go, if dealer has no Possible Blackjack
    dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
    if dealer.DealerHandPossibleBlackjack() = false
      me.blackjackGameEvents = PlayerOptions
      me.blackjackGameEventTimer.fireRate = 00:00:01
      me.blackjackGameEventTimer.start()
    .
  .
  return
.
// We trust that the player that has hit was allowed to do so
// Can always add a check to see if it is their turn
remote method Hit(playerID as ID)
  player as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
  hand as Integer = player.blackjackPlayerHandIndex
 
  me.DealCardToPlayer(player,hand)
  // After the player hits, we need to check their hand
  if player.HandTotal(0) >= 21
    println("Hand" + hand + "Busted")

    if player.LastHand()
      me.NextPlayer(player)
    .
  .
.

remote method Stand(playerID as ID)
  player as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
 
  if player.PlayerSplitHand() and player.blackjackPlayerHandIndex != 2
    player.NextHand()
   
  else if player.blackjackPlayerHandIndex = 2
    println("Player Stands and HI is:" + player.blackjackPlayerHandIndex)
    me.NextPlayer(player)
 
  else if (player.blackjackHands.length = 1 and player.PlayerSplitHand() = false)
    println("Player stands and didnt split")
    me.NextPlayer(player)
  .
.
// ToDo: check to make sure required funds are availible
// ToDO: Check for Ace split for special conditions
remote method Split(playerID as ID)
  player as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
  if player.CanSplitHand()
    secondCard as Enum Cards = player.blackjackHands[1][2]
    newHand as List of Enum Cards
    amount as Integer = player.blackjackHandWagers[1] * -1
    add back secondCard to newHand
   
    remove player.blackjackHands[1] at 2
   
    player.blackjackHands[2] = newHand
    insert player.blackjackHandWagers[1] to player.blackjackHandWagers at 2
    player.SetPlayerBalance(amount)
    println("Number of Hands: " + player.blackjackHands.length)
   
  .
.

method StartRound()
  me.ShuffleDeck()
  me.blackjackGameEvents = PreBet
  me.blackjackGameEventTimer.fireRate = 00:00:02
  me.blackjackGameEventTimer.start()
.

method NextEvent()
  me.blackjackGameEventTimer.stop()
 
  gameEvent as Enum blackjackGameEvent = me.blackjackGameEvents
  when gameEvent
    is PreBet
      me.blackjackGameEvents = Betting
      me.blackjackGameEventTimer.fireRate = 00:00:10
      me.blackjackGameEventTimer.start()

    .
    is Betting
      println("Betting round is OVER")
      // Betting is over
      // Deal all initial cards
      me.blackjackGameEvents = DealInitialCards
      dealList as List of ID = me.GetDealList()
      me.blackjackDealList = dealList
      me.DealCardsToAllPlayers()
    .
    is PlayerOptions
      println("Player's Turn")
      firstPlayer as Integer = me.GetNextPlayerPosition(0)
      player as NodeRef of Class BlackjackPlayer = me.blackjackGameSeatingOrder[firstPlayer]
      me.PlayerTurn(player)
    .
    is Dealer
      dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
      me.PlayerTurn(dealer)
    .
  .
.

method PlayerTurn(playerID as ID)
  player as NodeRef = playerID
  where player
    is kindof BlackjackPlayer
      me.ChangeCurrentPlayer(player)
      hand as Integer = player.blackjackPlayerHandIndex
 
      if player = me.blackjackCurrentPlayer
        blackjackHand as Boolean = player.HandIsBlackjack()
        if blackjackHand
          dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
          println("Hand" + hand + "Is a BlackJack!")
          // Player has Blackjack
          //Since there is  nothing else for the player to do
          //Go to the next player if the dealer doesnt have a possible blackjack
          //Pay out to the player
          // Pay out wager * 1.5 for blackjack
          wager as Integer = player.blackjackHandWagers[1]
          payout as Integer = RoundDown(wager * 1.5) + wager
          println("BlackJack Pay Out: " + payout)
          player.SetPlayerBalance(payout)
          me.NextPlayer(player)
        .
        println("Hand" + player.blackjackPlayerHandIndex)
   
      else
        println("Not your turn!")
      .
    .
   
    is kindof BlackjackDealer
      me.ChangeCurrentPlayer(player)
     
      dealerHandTotal as Integer = player.DealerHandTotal()
      dealerHandIsSoft as Boolean = player.DealerHandIsSoft()
     
      me.blackjackCardDealDelay.fireRate = 00:00:01
     
      if dealerHandTotal < 17 and dealerHandIsSoft = false
        me.DealCardToPlayer(player,1)
        me.blackjackCardDealDelay.start()
      else if dealerHandTotal < 18 and dealerHandIsSoft = true
        me.DealCardToPlayer(player,1)
        me.blackjackCardDealDelay.start()
      else if dealerHandTotal > 21
        println("Dealer Busted")
        me.CheckAllPlayers(0)
      else
        println("Dealer cant hit and has: " + dealerHandTotal)
        me.CheckAllPlayers(0)
      .
      println("Dealer Hand Total: " + player.DealerHandTotal())
    .
  .
.

// Check all players against the dealers hand
method CheckAllPlayers(playerID as ID)
  me.ChangeCurrentPlayer(playerID)
  player as NodeRef of Class BlackjackPlayer = playerID
  dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
 
  if player != 0 and player.HandIsBlackjack() = false and dealer.DealerHandIsBlackjack() = false
    foreach hand in player.blackjackHands
     
      if dealer.DealerHandTotal() <= 21
        if player.HandTotal(hand) < dealer.DealerHandTotal()
          println("hand " + hand + " lost")
         
        else if player.HandTotal(hand) <= 21
          if player.HandTotal(hand) > dealer.DealerHandTotal()
            wager as Integer = player.blackjackHandWagers[hand] * 2
            player.SetPlayerBalance(wager)

            println("hand " + hand + " Won")
            //If there is a push
          else if player.HandTotal(hand) = dealer.DealerHandTotal()
            wager as Integer = player.blackjackHandWagers[hand]
            player.SetPlayerBalance(wager)
            println("Hand " + hand + "Pushed with: " + player.HandTotal(hand))
          .
        .
      else if dealer.DealerHandTotal() > 21
        if player.HandTotal(hand) <= 21
          wager as Integer = player.blackjackHandWagers[hand] * 2
          player.SetPlayerBalance(wager)

          println("Dealer Busted, hand " + hand + " Won")

        .
      .
    .
  .
  if player != 0 and dealer.DealerHandIsBlackjack()
    if player.HandIsBlackjack()
      println("Blackjack Push")
      //Give back their money they wagered
      wager as Integer = player.blackjackHandWagers[1]
      player.SetPlayerBalance(wager)
    else
      println("Lost against Blackjack")
    .
  .
  me.checkForPlayerAgainstDealer.fireRate = 00:00:01
  me.checkForPlayerAgainstDealer.start()

.
 

//Start the next players turn
method NextPlayer(currentPlayerID as ID)
  nextPlayer as ID
  nextPlayerPos as Integer
  loop i from 1 to me.blackjackGameSeatingOrder.length
    if currentPlayerID = me.blackjackGameSeatingOrder[i]
      nextPlayerPos = me.GetNextPlayerposition(i)
      nextPlayer = me.blackjackGameSeatingOrder[nextPlayerPos]
      break
    .
  .
  // If the next player isn't "8" (the dealer)
  if nextPlayerPos != 8
    me.PlayerTurn(nextPlayer)
  else
    // It is the dealers turn
    me.blackjackGameEvents = Dealer
    me.NextEvent()
    println("Dealers turn")
  .
.
//Get the next players ID
method GetNextPlayer(currentPlayerID as ID) as ID
  nextPlayer as ID
  nextPlayerPos as Integer
 
  if currentPlayerID = 0
    return me.blackjackGameSeatingOrder[1]
  .
  loop i from 1 to me.blackjackGameSeatingOrder.length
    if currentPlayerID = me.blackjackGameSeatingOrder[i]
      nextPlayerPos = me.GetNextPlayerposition(i)
      nextPlayer = me.blackjackGameSeatingOrder[nextPlayerPos]
      break
    .
  .
  return nextPlayer
.

remote method RemovePlayerCards(playerID as ID)
  player as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
  dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
  player.ResetPlayer()
  dealer.ResetDealer()
.

// Intial wager amount for the first hand
remote method WagerAmount(amount as Integer, playerID as ID)
  player as NodeRef of Class BlackjackPlayer = me.GetBlackjackPlayerData(playerID)
  wager  as Integer = IABS(amount)
 
  if wager <= player.blackjackPlayerBalance
    // Is always going to be hand 1
    hand as Integer = 1
    player.SetPlayerBalance(amount)
    player.SetPlayerWager(wager,hand)
  .
  me.StartRound()
.

// Changes the current player

method ChangeCurrentPlayer(player as ID)
  me.blackjackCurrentPlayer = player
  println("CurrentPlayer ID IS: " + me.blackjackCurrentPlayer)
.
// The deal list is a list of players, and the dealer to deal cards to
method GetDealList() as List of ID
  theList as List of ID
  firstPlayer as Integer
  loop i from 1 to me.blackjackGameSeatingOrder.length
    if me.blackjackGameSeatingOrder[i] != 0
      firstPlayer = i
      break
    .
  .
   
  add back me.blackjackGameSeatingOrder[firstPlayer] to theList
   
 
  nextPlayer as Integer = me.GetNextPlayerPosition(firstPlayer)
 
  while firstPlayer != nextPlayer
    add back me.blackjackGameSeatingOrder[nextPlayer] to theList
    nextPlayer = me.GetNextPlayerPosition(nextPlayer)
  .
 
  add back theList to theList // add a second copy at the end so we deal 2 cards each
  return theList
.

method GetNextPlayerposition(position as Integer) as Integer
  // returns the next seat to the left of the provided position that is occupied by an active player
  // "active" requires that the player not be sitting out
  // if the provided position is 0, this will return the "first" occupied position
  // if no seats are occupied, this will return 0
  // if the only occupied seat is the provided position, it will be returned
  //From HJRef
  playerID as ID
  if position == 0
    loop i from 1 to me.blackjackGameSeatingOrder.length
      playerID = me.blackjackGameSeatingOrder[i]
      if playerID != 0
        return i
      .
    .
  else
    temp as Integer = position
    if temp >= me.blackjackGameSeatingOrder.length
      temp = 0
    .
    loop i from temp+1 to me.blackjackGameSeatingOrder.length
      playerID = me.blackjackGameSeatingOrder[i]
      if playerID != 0
        return i
      .
    .
    loop i from 1 to temp
      playerID = me.blackjackGameSeatingOrder[i]
      if playerID != 0
        return i
      .
    .
  .
  return 0
.

method GetBlackjackPlayerData(playerID as ID) as NodeRef of Class BlackjackPlayer
  player as NodeRef of Class BlackjackPlayer = me.blackjackPlayers[playerID]
  return player
.


method GetDealer() as NodeRef of Class BlackjackDealer
  dealer as NodeRef of Class BlackjackDealer
  dealer = QueryAssociationOneTargetByClass(me,"base_hard_association","BlackjackDealer")
  return dealer
.
// Send an event message to all players
method SendPlayerEventToAllPlayers(event as String, playerID as ID)
  player as NodeRef = playerID
  where player
    is kindof BlackjackPlayer
     
      call clientReplicas me.RecievePlayerEvent(event)
    .
    is kindof BlackjackDealer
     
      call clientReplicas me.RecievePlayerEvent(event)
    .
  .
.
//****************Timer_Ticks*************
method blackjackGameEventTimer_tick()
  gameEvent as Enum blackjackGameEvent = me.blackjackGameEvents
  me.NextEvent()
.

method checkForBlackjackDelayTimer_tick()
  me.checkForBlackjackDelayTimer.stop()
 
  d as NodeRef of Class BlackjackDealer = me.GetDealer()
  if d.DealerHandIsBlackjack()
    me.SendPlayerEventToAllPlayers("Dealer Has A Blackjack!",d)
    me.blackjackGameEvents = Dealer
    println("Dealer Has Blackjack!")
   
    me.CheckAllPlayers(0) 
  else
    // Dealer Doesn't have a Blackjack So it's now the players turn
    me.blackjackGameEvents = PlayerOptions
    me.blackjackGameEventTimer.fireRate = 00:00:01
    me.blackjackGameEventTimer.start()
    me.SendPlayerEventToAllPlayers("Dealer Does Not Have A Blackjack!",d)
    println("Dealer Does Not Have A Blackjack")
  .
.
//Used to delay any cards being dealt continuously
// For readability, it is probably better to split this up into two different methods
//One for initial cards being dealt, and another for the dealer's cards being dealt during the dealers's turn
method blackjackCardDealDelay_tick()
  gameEvent as Enum blackjackGameEvent = me.blackjackGameEvents
  // Is it time to deal the inital cards
  if gameEvent = DealInitialCards and me.blackjackDealList.length != 0
    player as ID = me.blackjackDealList[1]
    me.DealCardToPlayer(player,1)
    remove me.blackjackDealList at 1
    me.DealCardsToAllPlayers()
    // It is the dealer's turn
  else if gameEvent = Dealer
    me.blackjackCardDealDelay.stop()
    dealer as NodeRef of Class BlackjackDealer = me.GetDealer()
    me.PlayerTurn(dealer)
  .
.

method checkForPlayerAgainstDealer_tick()
  me.checkForPlayerAgainstDealer.stop()
  currentPlayer as ID = me.blackjackCurrentPlayer
 
  nextPlayer as ID = me.GetNextPlayer(currentPlayer)
  if nextPlayer != me.GetDealer()
    me.CheckAllPlayers(nextPlayer)
  .
.
//*************Replication**************
method _GetReplicationGroup(create as Boolean) as NodeRef of Class _ReplicationGroup
  replicationGroup as NodeRef of Class _ReplicationGroup = me._replicationGroupRef
 
  // During runtime, a reference is cached for speed.  If the cached reference is invalid, we do an exhaustive search in an
  //   attempt to locate an existing replication group.
  if me._replicationGroupRef = None
    foreach assoc in QueryAssociation(me,"base_hard_association",0)
      test as NodeRef = assoc.target
      if test is kindof _ReplicationGroup
        replicationGroup = test
        me._replicationGroupRef = replicationGroup
        break
      .
    .
  .
 
  if (replicationGroup = None and create)
    //Create replication group
    replicationGroup =  CreateNodeFromClass("_ReplicationGroup")
    AddAssociation(me,"base_hard_association",replicationGroup)
    replicationGroup._replicationPrimaryNode = me
   
    // Cached for fast lookup
    me._replicationGroupRef = replicationGroup
  .
  return replicationGroup
.



13
Off Topic / New HSL format on the forums and the green strings
« on: Aug 14, 12, 12:25:17 AM »
The new HSL formatting on the forums is awesome.
But the color for strings are green. Would it be possible to make them similar to the actual code we see in the HSL script editor?

It just seems odd after being used to them being yellow.


14
Scripting & Programming / [Resolved] proxy nodes
« on: Jul 20, 12, 06:25:57 PM »
I was able to replicate nodes from a system area, to a client in a different area successfully. That was easy :)

But I am curious if it is possible to add another client to recieve the replicated node if the node to be replicated is in a different area than they are currently in.

The above probably doesn't make sense.

Here is an example:

A node was created in the same area as PLAYER A

PLAYER B is in a different area, and needs that node in PLAYER A's area to be replicated to him.

Would you use proxy nodes?

15
For those that haven't seen it, I thought I would share this: http://www.gdcvault.com/play/1014345/I-Shot-You-First-Networking
It is about problems they ran into, and how they overcame it. Although it is about an FPS game, it might have some information that can be applied to any game that uses networking.



Pages: [1] 2