mirror of
https://github.com/psforever/PSF-LoginServer.git
synced 2026-01-19 18:44:45 +00:00
* Add .scalafmt.conf
* Adopt quill for database access
* Removed postgresql-async
* Refactored all instances of database access
* Creating duplicate characters of the same account is no longer possible
* Rewrote large parts of LoginSessionActor
* Implement migrations
* Move overrides into subdirectory
* Make usernames case insensitive
* Use LOWER(?) comparison instead of storing lowercased username
* import scala.util.{Success, Failure}
* Add config and joda-time dependencies
* Add sbt-scalafmt
* Use defaultWithAlign scalafmt preset
* Format all
* Add scalafix
* Remove unused imports
* Don't lowercase username when inserting
* Update readme
* Listen on worldserver.Hostname address
* Remove database test on startup
It could fail when the global thread pool is busy loading zone
maps. Migrations run on the main thread and also serve the
purpose of verifying the database configuration so it's fine to
remove the test altogether.
* Refactor chat message handlers, zones
What started as a small change to how zones are stored turned
into a pretty big effort of refactoring the chat message handler.
The !hack command was removed, the /capturebase commandwas added.
* Expose db ports in docker-compose.yml
* Silence property override log
* Rework configuration
* Unify configuration using the typesafe.config library
* Add configuration option for public address
* Configuration is now loaded from application.conf rather than worldserver.ini
* Refactor PsLogin and remove unnecessary logging
* Move pslogin into net.psforever.pslogin namespace
* Fix coverage
This commit is contained in:
parent
88b194fde2
commit
e0defe8240
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -13,8 +13,7 @@ out/
|
|||
project/metals.sbt
|
||||
|
||||
# User configs
|
||||
config/worldserver.ini
|
||||
pslogin/src/main/resources/user.conf
|
||||
config/psforever.conf
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
|
|
|
|||
6
.scalafix.conf
Normal file
6
.scalafix.conf
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
rules = [
|
||||
RemoveUnused
|
||||
]
|
||||
RemoveUnused.imports = true
|
||||
RemoveUnused.privates = false
|
||||
RemoveUnused.locals = false
|
||||
3
.scalafmt.conf
Normal file
3
.scalafmt.conf
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
version = 2.6.1
|
||||
preset = defaultWithAlign
|
||||
maxColumn = 120
|
||||
66
README.md
66
README.md
|
|
@ -78,7 +78,11 @@ The Login and World servers require PostgreSQL for persistence.
|
|||
- Linux - [Debian](https://www.postgresql.org/download/linux/debian/) or [Ubuntu](https://www.postgresql.org/download/linux/ubuntu/)
|
||||
- macOS - Application https://www.postgresql.org/download/ (or `brew install postgresql && brew services start postgresql`)
|
||||
|
||||
The default database is named `psforever` and the credentials are `psforever:psforever`. To change these, make a copy of [`config/worldserver.ini.dist`](config/worldserver.ini.dist) to `config/worldserver.ini` and change the corresponding fields in the database section. This database user will need ALL access to tables, sequences, and functions.
|
||||
The default database is named `psforever` and the credentials are
|
||||
`psforever:psforever`. To change these, create a configuration file at
|
||||
`config/psforever.conf`. For configuration options and their defaults, see
|
||||
[`pslogin/src/main/resources/application.conf`]. This database user will need
|
||||
ALL access to tables, sequences, and functions.
|
||||
The permissions required can be summarized by the SQL below.
|
||||
Loading this in requires access to a graphical tool such as [pgAdmin](https://www.pgadmin.org/download/) (highly recommended) or a PostgreSQL terminal (`psql`) for advanced users.
|
||||
|
||||
|
|
@ -95,9 +99,9 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA PUBLIC GRANT ALL ON FUNCTIONS TO psforever;
|
|||
|
||||
**NOTE:** applying default privileges _after_ importing the schema will not apply them to existing objects. To fix this, you must drop all objects and try again or apply permissions manually using the Query Tool / `psql`.
|
||||
|
||||
Now you need to synchronize the schema. This is currently available in [`schema.sql`](schema.sql).
|
||||
To do this right click on the psforever database -> Query Tool... -> Copy and paste / Open the `schema.sql` file into the editor -> Hit the "Play/Run" button. The schema should be loaded into the database.
|
||||
Once you have the schema loaded in, the LoginServer will automatically create accounts on first login. If you'd like a nice account management interface, check out the [PSFPortal](https://github.com/psforever/PSFPortal) web interface.
|
||||
The server will automatically apply the latest schema. Migrations can also be applied manually using
|
||||
the [Flyway CLI](https://flywaydb.org/documentation/commandline/). Existing databases before the
|
||||
introduction of migrations must be baselined using the `flyway baseline` command.
|
||||
|
||||
### Becoming a GM
|
||||
|
||||
|
|
@ -161,33 +165,6 @@ Using SBT, you can generate documentation for both the common and pslogin projec
|
|||
|
||||
Current documentation is available at [https://psforever.github.io/docs/master/index.html](https://psforever.github.io/docs/master/index.html)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
#### Unable to initialize pscrypto
|
||||
|
||||
If you get an error like below
|
||||
|
||||
```
|
||||
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
|
||||
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
|
||||
```
|
||||
|
||||
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
|
||||
|
||||
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
|
||||
|
||||
## Get in touch
|
||||
|
||||
- Website: http://psforever.net
|
||||
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
|
||||
- Join the #code channel and ask any questions you have there
|
||||
|
||||
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
|
||||
|
||||
## Tools
|
||||
|
||||
### decodePackets
|
||||
|
|
@ -217,6 +194,33 @@ psf-decode-packets -o ./output-directory foo.gcap bar.gcap
|
|||
By default, decodePackets takes in `.gcap` files, but it can also take gcapy ascii files with the
|
||||
`-p` option. Run `psf-decode-packets --help` to get usage info.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
#### Unable to initialize pscrypto
|
||||
|
||||
If you get an error like below
|
||||
|
||||
```
|
||||
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
|
||||
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
|
||||
```
|
||||
|
||||
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
|
||||
|
||||
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
|
||||
|
||||
## Get in touch
|
||||
|
||||
- Website: http://psforever.net
|
||||
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
|
||||
- Join the #code channel and ask any questions you have there
|
||||
|
||||
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
|
||||
|
||||
## License
|
||||
|
||||
GNU GPLv3. See LICENSE.md for the full copy.
|
||||
|
|
|
|||
160
build.sbt
160
build.sbt
|
|
@ -4,8 +4,18 @@ lazy val commonSettings = Seq(
|
|||
organization := "net.psforever",
|
||||
version := "1.0.2-SNAPSHOT",
|
||||
scalaVersion := "2.13.2",
|
||||
scalacOptions := Seq("-unchecked", "-feature", "-deprecation", "-encoding", "utf8", "-language:postfixOps"),
|
||||
|
||||
semanticdbEnabled := true,
|
||||
semanticdbVersion := scalafixSemanticdb.revision,
|
||||
scalacOptions := Seq(
|
||||
"-unchecked",
|
||||
"-feature",
|
||||
"-deprecation",
|
||||
"-encoding",
|
||||
"utf8",
|
||||
"-language:postfixOps",
|
||||
"-Wunused:imports",
|
||||
"-Xmacro-settings:materialize-derivations"
|
||||
),
|
||||
// Quiet test options
|
||||
// https://github.com/etorreborre/specs2/blob/8305db76c5084e4b3ce5827ce23117f6fb6beee4/common/shared/src/main/scala/org/specs2/main/Report.scala#L94
|
||||
// https://etorreborre.github.io/specs2/guide/SPECS2-2.4.17/org.specs2.guide.Runners.html
|
||||
|
|
@ -14,41 +24,56 @@ lazy val commonSettings = Seq(
|
|||
testOptions in QuietTest += Tests.Argument(TestFrameworks.ScalaTest, "-oCEHILMNOPQRX"),
|
||||
// Trick taken from https://groups.google.com/d/msg/scala-user/mxV9ok7J_Eg/kt-LnsrD0bkJ
|
||||
// scaladoc flags: https://github.com/scala/scala/blob/2.11.x/src/scaladoc/scala/tools/nsc/doc/Settings.scala
|
||||
scalacOptions in (Compile,doc) := { Seq(
|
||||
scalacOptions in (Compile, doc) ++= Seq(
|
||||
"-groups",
|
||||
"-implicits",
|
||||
"-doc-title", "PSF-LoginServer - ",
|
||||
"-doc-version", "master",
|
||||
"-doc-footer", "Copyright PSForever",
|
||||
"-doc-title",
|
||||
"PSF-LoginServer - ",
|
||||
"-doc-version",
|
||||
"master",
|
||||
"-doc-footer",
|
||||
"Copyright PSForever",
|
||||
// For non unidoc builds, you may need bd.getName before the template parameter
|
||||
"-doc-source-url", "https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala",
|
||||
"-sourcepath", baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths
|
||||
)
|
||||
},
|
||||
"-doc-source-url",
|
||||
"https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala",
|
||||
"-sourcepath",
|
||||
baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths
|
||||
),
|
||||
classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat,
|
||||
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
|
||||
libraryDependencies ++= Seq(
|
||||
"com.typesafe.akka" %% "akka-actor" % "2.6.5",
|
||||
"com.typesafe.akka" %% "akka-testkit" % "2.6.5" % "test",
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
|
||||
"org.specs2" %% "specs2-core" % "4.9.4" % "test",
|
||||
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
|
||||
"org.scodec" %% "scodec-core" % "1.11.7",
|
||||
"net.java.dev.jna" % "jna" % "5.5.0",
|
||||
"com.typesafe.akka" %% "akka-slf4j" % "2.6.5",
|
||||
"ch.qos.logback" % "logback-classic" % "1.2.3",
|
||||
"org.log4s" %% "log4s" % "1.8.2",
|
||||
"org.fusesource.jansi" % "jansi" % "1.12",
|
||||
"com.typesafe.akka" %% "akka-actor" % "2.6.6",
|
||||
"com.typesafe.akka" %% "akka-slf4j" % "2.6.6",
|
||||
"com.typesafe.akka" %% "akka-protobuf-v3" % "2.6.6",
|
||||
"com.typesafe.akka" %% "akka-stream" % "2.6.6",
|
||||
"com.typesafe.akka" %% "akka-testkit" % "2.6.6" % "test",
|
||||
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.6",
|
||||
"com.typesafe.akka" %% "akka-cluster-typed" % "2.6.6",
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
|
||||
"org.specs2" %% "specs2-core" % "4.9.4" % "test",
|
||||
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
|
||||
"org.scodec" %% "scodec-core" % "1.11.7",
|
||||
"net.java.dev.jna" % "jna" % "5.5.0",
|
||||
"com.typesafe.akka" %% "akka-slf4j" % "2.6.5",
|
||||
"ch.qos.logback" % "logback-classic" % "1.2.3",
|
||||
"org.log4s" %% "log4s" % "1.8.2",
|
||||
"org.fusesource.jansi" % "jansi" % "1.12",
|
||||
"org.scoverage" %% "scalac-scoverage-plugin" % "1.4.1",
|
||||
"com.github.nscala-time" %% "nscala-time" % "2.24.0",
|
||||
"com.github.postgresql-async" %% "postgresql-async" % "0.3.0",
|
||||
"com.github.t3hnar" %% "scala-bcrypt" % "4.1",
|
||||
"org.ini4j" % "ini4j" % "0.5.4",
|
||||
"org.scala-graph" %% "graph-core" % "1.13.1",
|
||||
"io.kamon" %% "kamon-bundle" % "2.1.0",
|
||||
"io.kamon" %% "kamon-apm-reporter" % "2.1.0",
|
||||
"org.json4s" %% "json4s-native" % "3.6.8",
|
||||
"com.typesafe.akka" %% "akka-stream" % "2.6.5"
|
||||
"com.github.nscala-time" %% "nscala-time" % "2.24.0",
|
||||
"com.github.t3hnar" %% "scala-bcrypt" % "4.1",
|
||||
"org.scala-graph" %% "graph-core" % "1.13.1",
|
||||
"io.kamon" %% "kamon-bundle" % "2.1.0",
|
||||
"io.kamon" %% "kamon-apm-reporter" % "2.1.0",
|
||||
"org.json4s" %% "json4s-native" % "3.6.8",
|
||||
"com.typesafe.akka" %% "akka-stream" % "2.6.5",
|
||||
"io.getquill" %% "quill-jasync-postgres" % "3.5.2",
|
||||
"org.flywaydb" % "flyway-core" % "6.5.0",
|
||||
"org.postgresql" % "postgresql" % "42.2.14",
|
||||
"com.typesafe" % "config" % "1.4.0",
|
||||
"com.github.pureconfig" %% "pureconfig" % "0.13.0",
|
||||
"com.beachape" %% "enumeratum" % "1.6.1",
|
||||
"joda-time" % "joda-time" % "2.10.6",
|
||||
"commons-io" % "commons-io" % "2.6"
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -61,63 +86,58 @@ lazy val pscryptoSettings = Seq(
|
|||
lazy val psloginPackSettings = Seq(
|
||||
packMain := Map("ps-login" -> "PsLogin"),
|
||||
packArchivePrefix := "pslogin",
|
||||
packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib",
|
||||
"${PROG_HOME}/config")),
|
||||
packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"),
|
||||
packResourceDir += (baseDirectory.value / "config" -> "config"),
|
||||
packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib", "${PROG_HOME}/config")),
|
||||
packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"),
|
||||
packResourceDir += (baseDirectory.value / "config" -> "config"),
|
||||
packResourceDir += (baseDirectory.value / "pslogin/src/main/resources" -> "config")
|
||||
)
|
||||
|
||||
lazy val root = (project in file(".")).
|
||||
configs(QuietTest).
|
||||
enablePlugins(PackPlugin).
|
||||
settings(commonSettings: _*).
|
||||
settings(psloginPackSettings: _*).
|
||||
enablePlugins(ScalaUnidocPlugin).
|
||||
aggregate(pslogin, common).
|
||||
dependsOn(pslogin, common)
|
||||
lazy val root = (project in file("."))
|
||||
.configs(QuietTest)
|
||||
.enablePlugins(PackPlugin)
|
||||
.settings(commonSettings: _*)
|
||||
.settings(psloginPackSettings: _*)
|
||||
.enablePlugins(ScalaUnidocPlugin)
|
||||
.aggregate(pslogin, common)
|
||||
|
||||
lazy val pslogin = (project in file("pslogin")).
|
||||
configs(QuietTest).
|
||||
settings(commonSettings: _*).
|
||||
settings(
|
||||
lazy val pslogin = (project in file("pslogin"))
|
||||
.configs(QuietTest)
|
||||
.settings(commonSettings: _*)
|
||||
.settings(
|
||||
name := "pslogin",
|
||||
// ActorTests have specific timing requirements and will be flaky if run in parallel
|
||||
parallelExecution in Test := false,
|
||||
// TODO(chord): remove exclusion when WorldSessionActor is refactored: https://github.com/psforever/PSF-LoginServer/issues/279
|
||||
coverageExcludedPackages := "WorldSessionActor.*;zonemaps.*",
|
||||
coverageExcludedPackages := "net.psforever.pslogin.WorldSessionActor.*;net.psforever.pslogin.zonemaps.*",
|
||||
// Copy all tests from Test -> QuietTest (we're only changing the run options)
|
||||
inConfig(QuietTest)(Defaults.testTasks)
|
||||
).
|
||||
settings(pscryptoSettings: _*).
|
||||
dependsOn(common)
|
||||
)
|
||||
.settings(pscryptoSettings: _*)
|
||||
.dependsOn(common)
|
||||
|
||||
lazy val common = (project in file("common")).
|
||||
configs(QuietTest).
|
||||
settings(commonSettings: _*).
|
||||
settings(
|
||||
lazy val common = (project in file("common"))
|
||||
.configs(QuietTest)
|
||||
.settings(commonSettings: _*)
|
||||
.settings(
|
||||
name := "common",
|
||||
// Copy all tests from Test -> QuietTest (we're only changing the run options)
|
||||
inConfig(QuietTest)(Defaults.testTasks)
|
||||
).
|
||||
settings(pscryptoSettings: _*)
|
||||
)
|
||||
.settings(pscryptoSettings: _*)
|
||||
|
||||
lazy val decodePackets = (project in file("tools/decode-packets")).
|
||||
enablePlugins(PackPlugin).
|
||||
settings(commonSettings: _*).
|
||||
settings(decodePacketsPackSettings: _*).
|
||||
settings(
|
||||
lazy val decodePackets = (project in file("tools/decode-packets"))
|
||||
.enablePlugins(PackPlugin)
|
||||
.settings(commonSettings: _*)
|
||||
.settings(decodePacketsPackSettings: _*)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0",
|
||||
"com.github.scopt" %% "scopt" % "4.0.0-RC2",
|
||||
"commons-io" % "commons-io" % "2.6"
|
||||
"org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0",
|
||||
"com.github.scopt" %% "scopt" % "4.0.0-RC2"
|
||||
)
|
||||
).
|
||||
dependsOn(common)
|
||||
)
|
||||
.dependsOn(common)
|
||||
|
||||
lazy val decodePacketsPackSettings = Seq(
|
||||
packMain := Map("psf-decode-packets" -> "DecodePackets"),
|
||||
)
|
||||
lazy val decodePacketsPackSettings = Seq(packMain := Map("psf-decode-packets" -> "DecodePackets"))
|
||||
|
||||
// Special test configuration for really quiet tests (used in CI)
|
||||
lazy val QuietTest = config("quiet") extend(Test)
|
||||
lazy val QuietTest = config("quiet") extend (Test)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
// Taken from http://code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/
|
||||
package akka.actor
|
||||
|
||||
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
|
||||
|
||||
import akka.util.Timeout
|
||||
import org.slf4j.MDC
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
trait MDCContextAware extends Actor with ActorLogging {
|
||||
trait MDCContextAware extends Actor with ActorLogging {
|
||||
import MDCContextAware._
|
||||
|
||||
// This is why this needs to be in package akka.actor
|
||||
|
|
@ -52,7 +52,7 @@ object MDCContextAware {
|
|||
* the current MDC values. Note: we MUST capture the ActorContext in order for senders
|
||||
* to be correct! This was a bug from the original author.
|
||||
*/
|
||||
def !>(msg: Any)(implicit context: ActorContext) : Unit =
|
||||
def !>(msg: Any)(implicit context: ActorContext): Unit =
|
||||
ref.tell(MdcMsg(MDC.getCopyOfContextMap, msg), context.self)
|
||||
|
||||
/**
|
||||
|
|
@ -63,4 +63,4 @@ object MDCContextAware {
|
|||
ref.ask(MdcMsg(MDC.getCopyOfContextMap, msg), context.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package akka.actor
|
||||
|
||||
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
|
||||
|
||||
import org.slf4j.MDC
|
||||
|
||||
import scala.concurrent.ExecutionContext
|
||||
|
||||
trait MDCPropagatingExecutionContext extends ExecutionContext {
|
||||
// name the self-type "self" so we can refer to it inside the nested class
|
||||
self =>
|
||||
|
||||
override def prepare(): ExecutionContext =
|
||||
new ExecutionContext {
|
||||
// Save the call-site MDC state
|
||||
val context = MDC.getCopyOfContextMap
|
||||
|
||||
def execute(r: Runnable): Unit =
|
||||
self.execute(new Runnable {
|
||||
def run(): Unit = {
|
||||
// Save the existing execution-site MDC state
|
||||
val oldContext = MDC.getCopyOfContextMap
|
||||
try {
|
||||
// Set the call-site MDC state into the execution-site MDC
|
||||
if (context != null)
|
||||
MDC.setContextMap(context)
|
||||
else
|
||||
MDC.clear()
|
||||
|
||||
r.run()
|
||||
} finally {
|
||||
// Restore the existing execution-site MDC state
|
||||
if (oldContext != null)
|
||||
MDC.setContextMap(oldContext)
|
||||
else
|
||||
MDC.clear()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
def reportFailure(t: Throwable): Unit = self.reportFailure(t)
|
||||
}
|
||||
}
|
||||
|
||||
object MDCPropagatingExecutionContext {
|
||||
object Implicits {
|
||||
// Convenience wrapper around the Scala global ExecutionContext so you can just do:
|
||||
// import MDCPropagatingExecutionContext.Implicits.global
|
||||
implicit lazy val global = MDCPropagatingExecutionContextWrapper(ExecutionContext.Implicits.global)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around an existing ExecutionContext that makes it propagate MDC information.
|
||||
*/
|
||||
class MDCPropagatingExecutionContextWrapper(wrapped: ExecutionContext)
|
||||
extends ExecutionContext
|
||||
with MDCPropagatingExecutionContext {
|
||||
|
||||
override def execute(r: Runnable): Unit = wrapped.execute(r)
|
||||
|
||||
override def reportFailure(t: Throwable): Unit = wrapped.reportFailure(t)
|
||||
}
|
||||
|
||||
object MDCPropagatingExecutionContextWrapper {
|
||||
def apply(wrapped: ExecutionContext): MDCPropagatingExecutionContextWrapper = {
|
||||
new MDCPropagatingExecutionContextWrapper(wrapped)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever
|
||||
|
||||
class ObjectFinalizedException(msg : String) extends Exception(msg)
|
||||
class ObjectFinalizedException(msg: String) extends Exception(msg)
|
||||
|
||||
trait IFinalizable {
|
||||
var closed = false
|
||||
|
|
@ -11,12 +11,14 @@ trait IFinalizable {
|
|||
}
|
||||
|
||||
def assertNotClosed = {
|
||||
if(closed)
|
||||
throw new ObjectFinalizedException(this.getClass.getCanonicalName + ": already finalized. Cannot interact with object")
|
||||
if (closed)
|
||||
throw new ObjectFinalizedException(
|
||||
this.getClass.getCanonicalName + ": already finalized. Cannot interact with object"
|
||||
)
|
||||
}
|
||||
|
||||
override def finalize() = {
|
||||
if(!closed)
|
||||
if (!closed)
|
||||
println(this.getClass.getCanonicalName + ": class not closed. memory leaked")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,240 +0,0 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
package net.psforever.config
|
||||
|
||||
import org.ini4j
|
||||
import scala.reflect.ClassTag
|
||||
import scala.reflect.runtime.universe.TypeTag
|
||||
import scala.annotation.implicitNotFound
|
||||
import scala.concurrent.duration._
|
||||
import scala.collection.mutable.Map
|
||||
|
||||
case class ConfigValueMapper[T](name: String)(f: (String => Option[T])) {
|
||||
def apply(t: String): Option[T] = f(t)
|
||||
}
|
||||
|
||||
object ConfigValueMapper {
|
||||
import scala.language.implicitConversions
|
||||
|
||||
implicit val toInt : ConfigValueMapper[Int] = ConfigValueMapper[Int]("toInt") { e =>
|
||||
try {
|
||||
Some(e.toInt)
|
||||
} catch {
|
||||
case e: Exception => None
|
||||
}
|
||||
}
|
||||
|
||||
// TypeTag is necessary to be able to retrieve an instance of the Enum class
|
||||
// at runtime as it is usually erased at runtime. This is low cost as its only
|
||||
// used during the config parsing
|
||||
implicit def toEnum[E <: Enumeration#Value](implicit m: TypeTag[E]) : ConfigValueMapper[E] = ConfigValueMapper[E]("toEnum") { e =>
|
||||
try {
|
||||
Some(EnumReflector.withName[E](e))
|
||||
} catch {
|
||||
case e: Exception => None
|
||||
}
|
||||
}
|
||||
|
||||
implicit val toBool : ConfigValueMapper[Boolean] = ConfigValueMapper[Boolean]("toBool") { e =>
|
||||
if (e == "yes") {
|
||||
Some(true)
|
||||
} else if (e == "no") {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
implicit val toFloat : ConfigValueMapper[Float] = ConfigValueMapper[Float]("toFloat") { e =>
|
||||
try {
|
||||
Some(e.toFloat)
|
||||
} catch {
|
||||
case e: Exception => None
|
||||
}
|
||||
}
|
||||
|
||||
implicit val toDuration : ConfigValueMapper[Duration] = ConfigValueMapper[Duration]("toDuration") { e =>
|
||||
try {
|
||||
Some(Duration(e))
|
||||
} catch {
|
||||
case e: Exception => None
|
||||
}
|
||||
}
|
||||
|
||||
implicit val toStr : ConfigValueMapper[String] = ConfigValueMapper[String]("toString") { e =>
|
||||
Some(e)
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait ConfigEntry {
|
||||
type Value
|
||||
val key : String
|
||||
val default : Value
|
||||
def getType : String
|
||||
val constraints : Seq[Constraint[Value]]
|
||||
def read(v: String): Option[Value]
|
||||
}
|
||||
|
||||
final case class ConfigEntryString(key: String, default : String, constraints : Constraint[String]*) extends ConfigEntry {
|
||||
type Value = String
|
||||
def getType = "String"
|
||||
def read(v : String) = ConfigValueMapper.toStr(v)
|
||||
}
|
||||
|
||||
final case class ConfigEntryInt(key: String, default : Int, constraints : Constraint[Int]*) extends ConfigEntry {
|
||||
type Value = Int
|
||||
def getType = "Int"
|
||||
def read(v : String) = ConfigValueMapper.toInt(v)
|
||||
}
|
||||
|
||||
final case class ConfigEntryBool(key: String, default : Boolean, constraints : Constraint[Boolean]*) extends ConfigEntry {
|
||||
type Value = Boolean
|
||||
def getType = "Bool"
|
||||
def read(v : String) = ConfigValueMapper.toBool(v)
|
||||
}
|
||||
|
||||
final case class ConfigEntryEnum[E <: Enumeration](key: String, default : E#Value)(implicit m : TypeTag[E#Value], implicit val m2 : TypeTag[E#ValueSet]) extends ConfigEntry {
|
||||
type Value = E#Value
|
||||
val constraints : Seq[Constraint[E#Value]] = Seq()
|
||||
def getType = EnumReflector.values[E#ValueSet](m2).mkString(", ")
|
||||
def read(v : String) = ConfigValueMapper.toEnum[E#Value](m)(v)
|
||||
}
|
||||
|
||||
final case class ConfigEntryFloat(key: String, default : Float, constraints : Constraint[Float]*) extends ConfigEntry {
|
||||
type Value = Float
|
||||
def getType = "Float"
|
||||
def read(v : String) = ConfigValueMapper.toFloat(v)
|
||||
}
|
||||
|
||||
final case class ConfigEntryTime(key: String, default : Duration, constraints : Constraint[Duration]*) extends ConfigEntry {
|
||||
type Value = Duration
|
||||
def getType = "Time"
|
||||
def read(v : String) = ConfigValueMapper.toDuration(v)
|
||||
}
|
||||
|
||||
case class ConfigSection(name: String, entries: ConfigEntry*)
|
||||
|
||||
@implicitNotFound("Nothing was inferred")
|
||||
sealed trait ConfigTypeRequired[-T]
|
||||
|
||||
object ConfigTypeRequired {
|
||||
implicit object cfgTypeRequired extends ConfigTypeRequired[Any]
|
||||
//We do not want Nothing to be inferred, so make an ambiguous implicit
|
||||
implicit object `\n The Get[T] call needs a type T matching the corresponding ConfigEntry` extends ConfigTypeRequired[Nothing]
|
||||
}
|
||||
|
||||
trait ConfigParser {
|
||||
protected var config_map : Map[String, Any] = Map()
|
||||
protected val config_template : Seq[ConfigSection]
|
||||
|
||||
// Misuse of this function can lead to run time exceptions when the types don't match
|
||||
// ClassTag is needed due to type erasure on T
|
||||
// https://dzone.com/articles/scala-classtag-a-simple-use-case
|
||||
def Get[T : ConfigTypeRequired](key : String)(implicit m: ClassTag[T]) : T = {
|
||||
config_map.get(key) match {
|
||||
case Some(value : T) => value
|
||||
case None =>
|
||||
throw new NoSuchElementException(s"Config key '${key}' not found")
|
||||
case Some(value : Any) =>
|
||||
throw new ClassCastException(s"Incorrect type T = ${m.runtimeClass.getSimpleName} passed to Get[T]: needed ${value.getClass.getSimpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
def Load(filename : String) : ValidationResult = {
|
||||
var map : Map[String, Any] = scala.collection.mutable.Map()
|
||||
|
||||
LoadMap(filename, map) match {
|
||||
case i : Invalid =>
|
||||
i
|
||||
case Valid =>
|
||||
ReplaceConfig(map)
|
||||
// run post-parse validation only if we successfully parsed
|
||||
postParseChecks match {
|
||||
case i : Invalid =>
|
||||
i
|
||||
case Valid =>
|
||||
Valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def LoadMap(filename : String, map : Map[String, Any]) : ValidationResult = {
|
||||
val ini = new org.ini4j.Ini()
|
||||
|
||||
try {
|
||||
ini.load(new java.io.File(filename))
|
||||
} catch {
|
||||
case e : org.ini4j.InvalidFileFormatException =>
|
||||
return Invalid(e.getMessage)
|
||||
case e : java.io.FileNotFoundException =>
|
||||
return Invalid(e.getMessage)
|
||||
}
|
||||
|
||||
val result : Seq[ValidationResult] = config_template.map { section =>
|
||||
val sectionIni = ini.get(section.name)
|
||||
|
||||
if (sectionIni == null)
|
||||
Seq(Invalid("section.missing", section.name))
|
||||
else
|
||||
section.entries.map(parseSection(sectionIni, _, map))
|
||||
}.reduceLeft((x, y) => x ++ y)
|
||||
|
||||
val errors : Seq[Invalid] = result.collect { case iv : Invalid => iv }
|
||||
|
||||
if (errors.length > 0)
|
||||
errors.reduceLeft((x, y) => x ++ y)
|
||||
else
|
||||
Valid
|
||||
}
|
||||
|
||||
def ReplaceConfig(map : Map[String, Any]) : Unit = {
|
||||
config_map = map
|
||||
}
|
||||
|
||||
def GetRawConfig : Map[String, Any] = {
|
||||
config_map
|
||||
}
|
||||
|
||||
def FormatErrors(invalidResult : Invalid) : Seq[String] = {
|
||||
var count = 0;
|
||||
|
||||
invalidResult.errors.map((error) => {
|
||||
var message = error.message;
|
||||
|
||||
if (error.args.length > 0)
|
||||
message += " ("+error.args(0)+")"
|
||||
|
||||
count += 1;
|
||||
s"Error ${count}: ${message}"
|
||||
});
|
||||
}
|
||||
|
||||
protected def postParseChecks : ValidationResult = {
|
||||
Valid
|
||||
}
|
||||
|
||||
protected def parseSection(sectionIni : org.ini4j.Profile.Section, entry : ConfigEntry, map : Map[String, Any]) : ValidationResult = {
|
||||
var rawValue = sectionIni.get(entry.key, 0)
|
||||
val full_key : String = sectionIni.getName + "." + entry.key
|
||||
|
||||
val value = if (rawValue == null) {
|
||||
println(s"config warning: missing key '${entry.key}', using default value '${entry.default}'")
|
||||
entry.default
|
||||
} else {
|
||||
rawValue = rawValue.stripPrefix("\"").stripSuffix("\"")
|
||||
|
||||
entry.read(rawValue) match {
|
||||
case Some(v) => v
|
||||
case None => return Invalid(ValidationError(String.format("%s: value format error (expected: %s)", full_key, entry.getType)))
|
||||
}
|
||||
}
|
||||
|
||||
map += (full_key -> value)
|
||||
|
||||
ParameterValidator(entry.constraints, Some(value)) match {
|
||||
case v @ Valid => v
|
||||
case i @ Invalid(errors) => {
|
||||
Invalid(errors.map(x => ValidationError(x.messages.map(full_key + ": " + _), x.args: _*)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
// Lifted from https://raw.githubusercontent.com/playframework/playframework/2.7.x/core/play/src/main/scala/play/api/data/validation/Validation.scala
|
||||
package net.psforever.config
|
||||
|
||||
|
||||
/**
|
||||
* A form constraint.
|
||||
*
|
||||
* @tparam T type of values handled by this constraint
|
||||
* @param name the constraint name, to be displayed to final user
|
||||
* @param args the message arguments, to format the constraint name
|
||||
* @param f the validation function
|
||||
*/
|
||||
case class Constraint[-T](name: Option[String], args: Seq[Any])(f: (T => ValidationResult)) {
|
||||
|
||||
/**
|
||||
* Run the constraint validation.
|
||||
*
|
||||
* @param t the value to validate
|
||||
* @return the validation result
|
||||
*/
|
||||
def apply(t: T): ValidationResult = f(t)
|
||||
}
|
||||
|
||||
/**
|
||||
* This object provides helpers for creating `Constraint` values.
|
||||
*
|
||||
* For example:
|
||||
* {{{
|
||||
* val negative = Constraint[Int] {
|
||||
* case i if i < 0 => Valid
|
||||
* case _ => Invalid("Must be a negative number.")
|
||||
* }
|
||||
* }}}
|
||||
*/
|
||||
object Constraint {
|
||||
|
||||
/**
|
||||
* Creates a new anonymous constraint from a validation function.
|
||||
*
|
||||
* @param f the validation function
|
||||
* @return a constraint
|
||||
*/
|
||||
def apply[T](f: (T => ValidationResult)): Constraint[T] = apply(None, Nil)(f)
|
||||
|
||||
/**
|
||||
* Creates a new named constraint from a validation function.
|
||||
*
|
||||
* @param name the constraint name
|
||||
* @param args the constraint arguments, used to format the constraint name
|
||||
* @param f the validation function
|
||||
* @return a constraint
|
||||
*/
|
||||
def apply[T](name: String, args: Any*)(f: (T => ValidationResult)): Constraint[T] = apply(Some(name), args.toSeq)(f)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a set of built-in constraints.
|
||||
*/
|
||||
object Constraints extends Constraints
|
||||
|
||||
/**
|
||||
* Defines a set of built-in constraints.
|
||||
*
|
||||
* @define emailAddressDoc Defines an ‘emailAddress’ constraint for `String` values which will validate email addresses.
|
||||
*
|
||||
* '''name'''[constraint.email]
|
||||
* '''error'''[error.email]
|
||||
*
|
||||
* @define nonEmptyDoc Defines a ‘required’ constraint for `String` values, i.e. one in which empty strings are invalid.
|
||||
*
|
||||
* '''name'''[constraint.required]
|
||||
* '''error'''[error.required]
|
||||
*/
|
||||
trait Constraints {
|
||||
|
||||
private val emailRegex =
|
||||
"""^[a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r
|
||||
|
||||
/**
|
||||
* $emailAddressDoc
|
||||
*/
|
||||
def emailAddress(errorMessage: String = "error.email"): Constraint[String] = Constraint[String]("constraint.email") {
|
||||
e =>
|
||||
if (e == null) Invalid(ValidationError(errorMessage))
|
||||
else if (e.trim.isEmpty) Invalid(ValidationError(errorMessage))
|
||||
else
|
||||
emailRegex
|
||||
.findFirstMatchIn(e)
|
||||
.map(_ => Valid)
|
||||
.getOrElse(Invalid(ValidationError(errorMessage)))
|
||||
}
|
||||
|
||||
/**
|
||||
* $emailAddressDoc
|
||||
*
|
||||
*/
|
||||
def emailAddress: Constraint[String] = emailAddress()
|
||||
|
||||
/**
|
||||
* $nonEmptyDoc
|
||||
*/
|
||||
def nonEmpty(errorMessage: String = "error.required"): Constraint[String] =
|
||||
Constraint[String]("constraint.required") { o =>
|
||||
if (o == null) Invalid(ValidationError(errorMessage))
|
||||
else if (o.trim.isEmpty) Invalid(ValidationError(errorMessage))
|
||||
else Valid
|
||||
}
|
||||
|
||||
/**
|
||||
* $nonEmptyDoc
|
||||
*
|
||||
*/
|
||||
def nonEmpty: Constraint[String] = nonEmpty()
|
||||
|
||||
/**
|
||||
* Defines a minimum value for `Ordered` values, by default the value must be greater than or equal to the constraint parameter
|
||||
*
|
||||
* '''name'''[constraint.min(minValue)]
|
||||
* '''error'''[error.min(minValue)] or [error.min.strict(minValue)]
|
||||
*/
|
||||
def min[T](
|
||||
minValue: T,
|
||||
strict: Boolean = false,
|
||||
errorMessage: String = "error.min",
|
||||
strictErrorMessage: String = "error.min.strict"
|
||||
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.min", minValue) { o =>
|
||||
(ordering.compare(o, minValue).sign, strict) match {
|
||||
case (1, _) | (0, false) => Valid
|
||||
case (_, false) => Invalid(ValidationError(errorMessage, minValue))
|
||||
case (_, true) => Invalid(ValidationError(strictErrorMessage, minValue))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a maximum value for `Ordered` values, by default the value must be less than or equal to the constraint parameter
|
||||
*
|
||||
* '''name'''[constraint.max(maxValue)]
|
||||
* '''error'''[error.max(maxValue)] or [error.max.strict(maxValue)]
|
||||
*/
|
||||
def max[T](
|
||||
maxValue: T,
|
||||
strict: Boolean = false,
|
||||
errorMessage: String = "error.max",
|
||||
strictErrorMessage: String = "error.max.strict"
|
||||
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.max", maxValue) { o =>
|
||||
(ordering.compare(o, maxValue).sign, strict) match {
|
||||
case (-1, _) | (0, false) => Valid
|
||||
case (_, false) => Invalid(ValidationError(errorMessage, maxValue))
|
||||
case (_, true) => Invalid(ValidationError(strictErrorMessage, maxValue))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a minimum length constraint for `String` values, i.e. the string’s length must be greater than or equal to the constraint parameter
|
||||
*
|
||||
* '''name'''[constraint.minLength(length)]
|
||||
* '''error'''[error.minLength(length)]
|
||||
*/
|
||||
def minLength(length: Int, errorMessage: String = "error.minLength"): Constraint[String] =
|
||||
Constraint[String]("constraint.minLength", length) { o =>
|
||||
require(length >= 0, "string minLength must not be negative")
|
||||
if (o == null) Invalid(ValidationError(errorMessage, length))
|
||||
else if (o.size >= length) Valid
|
||||
else Invalid(ValidationError(errorMessage, length))
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a maximum length constraint for `String` values, i.e. the string’s length must be less than or equal to the constraint parameter
|
||||
*
|
||||
* '''name'''[constraint.maxLength(length)]
|
||||
* '''error'''[error.maxLength(length)]
|
||||
*/
|
||||
def maxLength(length: Int, errorMessage: String = "error.maxLength"): Constraint[String] =
|
||||
Constraint[String]("constraint.maxLength", length) { o =>
|
||||
require(length >= 0, "string maxLength must not be negative")
|
||||
if (o == null) Invalid(ValidationError(errorMessage, length))
|
||||
else if (o.size <= length) Valid
|
||||
else Invalid(ValidationError(errorMessage, length))
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a regular expression constraint for `String` values, i.e. the string must match the regular expression pattern
|
||||
*
|
||||
* '''name'''[constraint.pattern(regex)] or defined by the name parameter.
|
||||
* '''error'''[error.pattern(regex)] or defined by the error parameter.
|
||||
*/
|
||||
def pattern(
|
||||
regex: => scala.util.matching.Regex,
|
||||
name: String = "constraint.pattern",
|
||||
error: String = "error.pattern"
|
||||
): Constraint[String] = Constraint[String](name, () => regex) { o =>
|
||||
require(regex != null, "regex must not be null")
|
||||
require(name != null, "name must not be null")
|
||||
require(error != null, "error must not be null")
|
||||
|
||||
if (o == null) Invalid(ValidationError(error, regex))
|
||||
else regex.unapplySeq(o).map(_ => Valid).getOrElse(Invalid(ValidationError(error, name)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A validation result.
|
||||
*/
|
||||
sealed trait ValidationResult
|
||||
|
||||
/**
|
||||
* Validation was a success.
|
||||
*/
|
||||
case object Valid extends ValidationResult
|
||||
|
||||
/**
|
||||
* Validation was a failure.
|
||||
*
|
||||
* @param errors the resulting errors
|
||||
*/
|
||||
case class Invalid(errors: Seq[ValidationError]) extends ValidationResult {
|
||||
|
||||
/**
|
||||
* Combines these validation errors with another validation failure.
|
||||
*
|
||||
* @param other validation failure
|
||||
* @return a new merged `Invalid`
|
||||
*/
|
||||
def ++(other: Invalid): Invalid = Invalid(this.errors ++ other.errors)
|
||||
}
|
||||
|
||||
/**
|
||||
* This object provides helper methods to construct `Invalid` values.
|
||||
*/
|
||||
object Invalid {
|
||||
|
||||
/**
|
||||
* Creates an `Invalid` value with a single error.
|
||||
*
|
||||
* @param error the validation error
|
||||
* @return an `Invalid` value
|
||||
*/
|
||||
def apply(error: ValidationError): Invalid = Invalid(Seq(error))
|
||||
|
||||
/**
|
||||
* Creates an `Invalid` value with a single error.
|
||||
*
|
||||
* @param error the validation error message
|
||||
* @param args the validation error message arguments
|
||||
* @return an `Invalid` value
|
||||
*/
|
||||
def apply(error: String, args: Any*): Invalid = Invalid(Seq(ValidationError(error, args: _*)))
|
||||
}
|
||||
|
||||
object ParameterValidator {
|
||||
def apply[T](constraints: Iterable[Constraint[T]], optionalParam: Option[T]*) =
|
||||
optionalParam.flatMap {
|
||||
_.map { param =>
|
||||
constraints.flatMap {
|
||||
_(param) match {
|
||||
case i: Invalid => Some(i)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}.flatten match {
|
||||
case Nil => Valid
|
||||
case invalids =>
|
||||
invalids.reduceLeft { (a, b) =>
|
||||
a ++ b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A validation error.
|
||||
*
|
||||
* @param messages the error message, if more then one message is passed it will use the last one
|
||||
* @param args the error message arguments
|
||||
*/
|
||||
case class ValidationError(messages: Seq[String], args: Any*) {
|
||||
|
||||
lazy val message = messages.last
|
||||
|
||||
}
|
||||
|
||||
object ValidationError {
|
||||
|
||||
|
||||
def apply(message: String, args: Any*) = new ValidationError(Seq(message), args: _*)
|
||||
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) 2019 PSForever
|
||||
package net.psforever.config
|
||||
|
||||
import scala.reflect.runtime.universe._
|
||||
|
||||
/**
|
||||
* Scala [[Enumeration]] helpers implementing Scala versions of
|
||||
* Java's [[java.lang.Enum.valueOf(Class[Enum], String)]].
|
||||
* @author Dmitriy Yefremov (http://yefremov.net/blog/scala-enum-by-name/)
|
||||
*/
|
||||
object EnumReflector {
|
||||
|
||||
private val mirror: Mirror = runtimeMirror(getClass.getClassLoader)
|
||||
|
||||
/**
|
||||
* Returns a value of the specified enumeration with the given name.
|
||||
* @param name value name
|
||||
* @tparam T enumeration type
|
||||
* @return enumeration value, see [[scala.Enumeration.withName(String)]]
|
||||
*/
|
||||
def withName[T <: Enumeration#Value: TypeTag](name: String): T = {
|
||||
typeOf[T] match {
|
||||
case valueType @ TypeRef(enumType, _, _) =>
|
||||
val methodSymbol = factoryMethodSymbol(enumType, "withName")
|
||||
val moduleSymbol = enumType.termSymbol.asModule
|
||||
reflect(moduleSymbol, methodSymbol)(name).asInstanceOf[T]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of values of an enumeration
|
||||
* @tparam T enumeration type
|
||||
* @return possible enumeration values, see [[scala.Enumeration.values()]]
|
||||
*/
|
||||
def values[T <: Enumeration#ValueSet: TypeTag]: T = {
|
||||
typeOf[T] match {
|
||||
case valueType @ TypeRef(enumType, _, _) =>
|
||||
val methodSymbol = factoryMethodSymbol(enumType, "values")
|
||||
val moduleSymbol = enumType.termSymbol.asModule
|
||||
reflect(moduleSymbol, methodSymbol)().asInstanceOf[T]
|
||||
}
|
||||
}
|
||||
|
||||
private def factoryMethodSymbol(enumType: Type, name : String): MethodSymbol = {
|
||||
enumType.member(TermName(name)).asMethod
|
||||
}
|
||||
|
||||
private def reflect(module: ModuleSymbol, method: MethodSymbol)(args: Any*): Any = {
|
||||
val moduleMirror = mirror.reflectModule(module)
|
||||
val instanceMirror = mirror.reflect(moduleMirror.instance)
|
||||
instanceMirror.reflectMethod(method)(args:_*)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,33 +4,33 @@ package net.psforever.crypto
|
|||
import com.sun.jna.ptr.IntByReference
|
||||
import net.psforever.IFinalizable
|
||||
import sna.Library
|
||||
import com.sun.jna.{NativeLibrary, Pointer}
|
||||
import com.sun.jna.Pointer
|
||||
import scodec.bits.ByteVector
|
||||
|
||||
object CryptoInterface {
|
||||
final val libName = "pscrypto"
|
||||
final val fullLibName = libName
|
||||
final val libName = "pscrypto"
|
||||
final val fullLibName = libName
|
||||
final val PSCRYPTO_VERSION_MAJOR = 1
|
||||
final val PSCRYPTO_VERSION_MINOR = 1
|
||||
|
||||
/**
|
||||
NOTE: this is a single, global shared library for the entire server's crypto needs
|
||||
|
||||
Unfortunately, access to this object didn't used to be synchronized. I noticed that
|
||||
tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on
|
||||
a secret..."). This heisenbug was responsible for failed Travis test runs and developer
|
||||
issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in
|
||||
pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is
|
||||
`jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no
|
||||
sense and after banging my head on the wall for many hours, I assumed that something deep
|
||||
in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to
|
||||
pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized.
|
||||
This *appears* to have fixed the problem.
|
||||
*/
|
||||
* NOTE: this is a single, global shared library for the entire server's crypto needs
|
||||
*
|
||||
* Unfortunately, access to this object didn't used to be synchronized. I noticed that
|
||||
* tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on
|
||||
* a secret..."). This heisenbug was responsible for failed Travis test runs and developer
|
||||
* issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in
|
||||
* pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is
|
||||
* `jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no
|
||||
* sense and after banging my head on the wall for many hours, I assumed that something deep
|
||||
* in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to
|
||||
* pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized.
|
||||
* This *appears* to have fixed the problem.
|
||||
*/
|
||||
final val psLib = new Library(libName)
|
||||
|
||||
final val RC5_BLOCK_SIZE = 8
|
||||
final val MD5_MAC_SIZE = 16
|
||||
final val MD5_MAC_SIZE = 16
|
||||
|
||||
val functionsList = List(
|
||||
"PSCrypto_Init",
|
||||
|
|
@ -51,7 +51,7 @@ object CryptoInterface {
|
|||
* Used to initialize the crypto library at runtime. The version is checked and
|
||||
* all functions are mapped.
|
||||
*/
|
||||
def initialize() : Unit = {
|
||||
def initialize(): Unit = {
|
||||
// preload all library functions for speed
|
||||
functionsList foreach psLib.prefetch
|
||||
|
||||
|
|
@ -60,24 +60,26 @@ object CryptoInterface {
|
|||
|
||||
psLib.PSCrypto_Get_Version(libraryMajor, libraryMinor)[Unit]
|
||||
|
||||
if(!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) {
|
||||
throw new IllegalArgumentException(s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " +
|
||||
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR")
|
||||
if (!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) {
|
||||
throw new IllegalArgumentException(
|
||||
s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " +
|
||||
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for debugging object loading
|
||||
*/
|
||||
def printEnvironment() : Unit = {
|
||||
* Used for debugging object loading
|
||||
*/
|
||||
def printEnvironment(): Unit = {
|
||||
import java.io.File
|
||||
|
||||
val classpath = System.getProperty("java.class.path")
|
||||
val classpath = System.getProperty("java.class.path")
|
||||
val classpathEntries = classpath.split(File.pathSeparator)
|
||||
|
||||
val myLibraryPath = System.getProperty("user.dir")
|
||||
val jnaLibrary = System.getProperty("jna.library.path")
|
||||
val javaLibrary = System.getProperty("java.library.path")
|
||||
val jnaLibrary = System.getProperty("jna.library.path")
|
||||
val javaLibrary = System.getProperty("java.library.path")
|
||||
println("User dir: " + myLibraryPath)
|
||||
println("JNA Lib: " + jnaLibrary)
|
||||
println("Java Lib: " + javaLibrary)
|
||||
|
|
@ -87,13 +89,13 @@ object CryptoInterface {
|
|||
println("Required data model: " + System.getProperty("sun.arch.data.model"))
|
||||
}
|
||||
|
||||
def MD5MAC(key : ByteVector, message : ByteVector, bytesWanted : Int) : ByteVector = {
|
||||
def MD5MAC(key: ByteVector, message: ByteVector, bytesWanted: Int): ByteVector = {
|
||||
val out = Array.ofDim[Byte](bytesWanted)
|
||||
|
||||
// WARNING BUG: the function must be cast to something (even if void) otherwise it doesnt work
|
||||
val ret = psLib.MD5_MAC(key.toArray, key.length, message.toArray, message.length, out, out.length)[Boolean]
|
||||
|
||||
if(!ret)
|
||||
if (!ret)
|
||||
throw new Exception("MD5MAC failed to process")
|
||||
|
||||
ByteVector(out)
|
||||
|
|
@ -106,15 +108,15 @@ object CryptoInterface {
|
|||
* @param mac1 A MAC value
|
||||
* @param mac2 Another MAC value
|
||||
*/
|
||||
def verifyMAC(mac1 : ByteVector, mac2 : ByteVector) : Boolean = {
|
||||
def verifyMAC(mac1: ByteVector, mac2: ByteVector): Boolean = {
|
||||
var okay = true
|
||||
|
||||
// prevent byte by byte guessing
|
||||
if(mac1.length != mac2.length)
|
||||
if (mac1.length != mac2.length)
|
||||
return false
|
||||
|
||||
for(i <- 0 until mac1.length.toInt) {
|
||||
okay = okay && mac1{i} == mac2{i}
|
||||
for (i <- 0 until mac1.length.toInt) {
|
||||
okay = okay && mac1 { i } == mac2 { i }
|
||||
}
|
||||
|
||||
okay
|
||||
|
|
@ -124,22 +126,22 @@ object CryptoInterface {
|
|||
var started = false
|
||||
// these types MUST be Arrays of bytes for JNA to work
|
||||
val privateKey = Array.ofDim[Byte](16)
|
||||
val publicKey = Array.ofDim[Byte](16)
|
||||
val p = Array.ofDim[Byte](16)
|
||||
val g = Array.ofDim[Byte](16)
|
||||
var dhHandle = Pointer.NULL
|
||||
val publicKey = Array.ofDim[Byte](16)
|
||||
val p = Array.ofDim[Byte](16)
|
||||
val g = Array.ofDim[Byte](16)
|
||||
var dhHandle = Pointer.NULL
|
||||
|
||||
def start(modulus : ByteVector, generator : ByteVector) : Unit = {
|
||||
def start(modulus: ByteVector, generator: ByteVector): Unit = {
|
||||
assertNotClosed
|
||||
|
||||
if(started)
|
||||
if (started)
|
||||
throw new IllegalStateException("DH state has already been started")
|
||||
|
||||
psLib.synchronized {
|
||||
dhHandle = psLib.DH_Start(modulus.toArray, generator.toArray, privateKey, publicKey)[Pointer]
|
||||
}
|
||||
|
||||
if(dhHandle == Pointer.NULL)
|
||||
if (dhHandle == Pointer.NULL)
|
||||
throw new Exception("DH initialization failed!")
|
||||
|
||||
modulus.copyToArray(p, 0)
|
||||
|
|
@ -148,37 +150,37 @@ object CryptoInterface {
|
|||
started = true
|
||||
}
|
||||
|
||||
def start() : Unit = {
|
||||
def start(): Unit = {
|
||||
assertNotClosed
|
||||
|
||||
if(started)
|
||||
if (started)
|
||||
throw new IllegalStateException("DH state has already been started")
|
||||
|
||||
psLib.synchronized {
|
||||
dhHandle = psLib.DH_Start_Generate(privateKey, publicKey, p, g)[Pointer]
|
||||
}
|
||||
|
||||
if(dhHandle == Pointer.NULL)
|
||||
if (dhHandle == Pointer.NULL)
|
||||
throw new Exception("DH initialization failed!")
|
||||
|
||||
started = true
|
||||
}
|
||||
|
||||
def agree(otherPublicKey : ByteVector) = {
|
||||
if(!started)
|
||||
def agree(otherPublicKey: ByteVector) = {
|
||||
if (!started)
|
||||
throw new IllegalStateException("DH state has not been started")
|
||||
|
||||
val agreedValue = Array.ofDim[Byte](16)
|
||||
val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean]
|
||||
val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean]
|
||||
|
||||
if(!agreed)
|
||||
if (!agreed)
|
||||
throw new Exception("Failed to DH agree")
|
||||
|
||||
ByteVector.view(agreedValue)
|
||||
}
|
||||
|
||||
private def checkAndReturnView(array : Array[Byte]) = {
|
||||
if(!started)
|
||||
private def checkAndReturnView(array: Array[Byte]) = {
|
||||
if (!started)
|
||||
throw new IllegalStateException("DH state has not been started")
|
||||
|
||||
ByteVector.view(array)
|
||||
|
|
@ -201,7 +203,7 @@ object CryptoInterface {
|
|||
}
|
||||
|
||||
override def close = {
|
||||
if(started) {
|
||||
if (started) {
|
||||
// TODO: zero private key material
|
||||
psLib.synchronized {
|
||||
psLib.Free_DH(dhHandle)[Unit]
|
||||
|
|
@ -213,46 +215,45 @@ object CryptoInterface {
|
|||
}
|
||||
}
|
||||
|
||||
class CryptoState(val decryptionKey : ByteVector,
|
||||
val encryptionKey : ByteVector) extends IFinalizable {
|
||||
class CryptoState(val decryptionKey: ByteVector, val encryptionKey: ByteVector) extends IFinalizable {
|
||||
// Note that the keys must be returned as primitive Arrays for JNA to work
|
||||
var encCryptoHandle : Pointer = Pointer.NULL
|
||||
var decCryptoHandle : Pointer = Pointer.NULL
|
||||
var encCryptoHandle: Pointer = Pointer.NULL
|
||||
var decCryptoHandle: Pointer = Pointer.NULL
|
||||
|
||||
psLib.synchronized {
|
||||
encCryptoHandle = psLib.RC5_Init(encryptionKey.toArray, encryptionKey.length, true)[Pointer]
|
||||
decCryptoHandle = psLib.RC5_Init(decryptionKey.toArray, decryptionKey.length, false)[Pointer]
|
||||
}
|
||||
|
||||
if(encCryptoHandle == Pointer.NULL)
|
||||
if (encCryptoHandle == Pointer.NULL)
|
||||
throw new Exception("Encryption initialization failed!")
|
||||
|
||||
if(decCryptoHandle == Pointer.NULL)
|
||||
if (decCryptoHandle == Pointer.NULL)
|
||||
throw new Exception("Decryption initialization failed!")
|
||||
|
||||
def encrypt(plaintext : ByteVector) : ByteVector = {
|
||||
if(plaintext.length % RC5_BLOCK_SIZE != 0)
|
||||
def encrypt(plaintext: ByteVector): ByteVector = {
|
||||
if (plaintext.length % RC5_BLOCK_SIZE != 0)
|
||||
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
|
||||
|
||||
val ciphertext = Array.ofDim[Byte](plaintext.length.toInt)
|
||||
|
||||
val ret = psLib.RC5_Encrypt(encCryptoHandle, plaintext.toArray, plaintext.length, ciphertext)[Boolean]
|
||||
|
||||
if(!ret)
|
||||
if (!ret)
|
||||
throw new Exception("Failed to encrypt plaintext")
|
||||
|
||||
ByteVector.view(ciphertext)
|
||||
}
|
||||
|
||||
def decrypt(ciphertext : ByteVector) : ByteVector = {
|
||||
if(ciphertext.length % RC5_BLOCK_SIZE != 0)
|
||||
def decrypt(ciphertext: ByteVector): ByteVector = {
|
||||
if (ciphertext.length % RC5_BLOCK_SIZE != 0)
|
||||
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
|
||||
|
||||
val plaintext = Array.ofDim[Byte](ciphertext.length.toInt)
|
||||
|
||||
val ret = psLib.RC5_Decrypt(decCryptoHandle, ciphertext.toArray, ciphertext.length, plaintext)[Boolean]
|
||||
|
||||
if(!ret)
|
||||
if (!ret)
|
||||
throw new Exception("Failed to decrypt ciphertext")
|
||||
|
||||
ByteVector.view(plaintext)
|
||||
|
|
@ -267,17 +268,20 @@ object CryptoInterface {
|
|||
}
|
||||
}
|
||||
|
||||
class CryptoStateWithMAC(decryptionKey : ByteVector,
|
||||
encryptionKey : ByteVector,
|
||||
val decryptionMACKey : ByteVector,
|
||||
val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) {
|
||||
class CryptoStateWithMAC(
|
||||
decryptionKey: ByteVector,
|
||||
encryptionKey: ByteVector,
|
||||
val decryptionMACKey: ByteVector,
|
||||
val encryptionMACKey: ByteVector
|
||||
) extends CryptoState(decryptionKey, encryptionKey) {
|
||||
|
||||
/**
|
||||
* Performs a MAC operation over the message. Used when encrypting packets
|
||||
*
|
||||
* @param message the input message
|
||||
* @return ByteVector
|
||||
*/
|
||||
def macForEncrypt(message : ByteVector) : ByteVector = {
|
||||
def macForEncrypt(message: ByteVector): ByteVector = {
|
||||
MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
|
||||
}
|
||||
|
||||
|
|
@ -287,18 +291,18 @@ object CryptoInterface {
|
|||
* @param message the input message
|
||||
* @return ByteVector
|
||||
*/
|
||||
def macForDecrypt(message : ByteVector) : ByteVector = {
|
||||
def macForDecrypt(message: ByteVector): ByteVector = {
|
||||
MD5MAC(decryptionMACKey, message, MD5_MAC_SIZE)
|
||||
}
|
||||
|
||||
/**
|
||||
* MACs the plaintext message, encrypts it, and then returns the encrypted message with the
|
||||
* MAC appended to the end.
|
||||
*
|
||||
*
|
||||
* @param message Arbitrary set of bytes
|
||||
* @return ByteVector
|
||||
*/
|
||||
def macAndEncrypt(message : ByteVector) : ByteVector = {
|
||||
def macAndEncrypt(message: ByteVector): ByteVector = {
|
||||
encrypt(message) ++ MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.newcodecs
|
||||
|
||||
import scodec.{ Codec, SizeBound }
|
||||
import scodec.Codec
|
||||
import scodec.bits.BitVector
|
||||
|
||||
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]) extends Codec[A] {
|
||||
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A])
|
||||
extends Codec[A] {
|
||||
|
||||
private lazy val evaluatedCodec_true = codec_true
|
||||
|
||||
|
||||
private lazy val evaluatedCodec_false = codec_false
|
||||
|
||||
override def sizeBound = if (choice) evaluatedCodec_true.sizeBound else evaluatedCodec_false.sizeBound
|
||||
|
|
@ -26,6 +27,7 @@ private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true:
|
|||
evaluatedCodec_false.decode(buffer)
|
||||
}
|
||||
|
||||
override def toString = if(choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
|
||||
override def toString =
|
||||
if (choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,30 +4,33 @@ package net.psforever.newcodecs
|
|||
import scodec._
|
||||
import scodec.bits.BitVector
|
||||
|
||||
final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None) extends Codec[Vector[A]] {
|
||||
final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None)
|
||||
extends Codec[Vector[A]] {
|
||||
|
||||
def sizeBound = limit match {
|
||||
case None => SizeBound.unknown
|
||||
case Some(lim) => codec.sizeBound * lim.toLong
|
||||
}
|
||||
def sizeBound =
|
||||
limit match {
|
||||
case None => SizeBound.unknown
|
||||
case Some(lim) => codec.sizeBound * lim.toLong
|
||||
}
|
||||
|
||||
def encode(vector: Vector[A]) = Encoder.encodeSeq(firstCodec)(vector.slice(0,1)).map { bits =>
|
||||
def encode(vector: Vector[A]) =
|
||||
Encoder.encodeSeq(firstCodec)(vector.slice(0, 1)).map { bits =>
|
||||
if (vector.length > 1)
|
||||
bits ++ (Encoder.encodeSeq(codec)(vector.tail) getOrElse BitVector.empty)
|
||||
else
|
||||
bits
|
||||
}
|
||||
}
|
||||
|
||||
def decode(buffer: BitVector) : scodec.Attempt[scodec.DecodeResult[Vector[A]]] = {
|
||||
Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match {
|
||||
case Attempt.Successful(firstValue) =>
|
||||
Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match {
|
||||
case Attempt.Successful(secondValue) =>
|
||||
Attempt.successful(DecodeResult(firstValue.value ++ secondValue.value, secondValue.remainder))
|
||||
case Attempt.Failure(e) => Attempt.failure(e)
|
||||
}
|
||||
case Attempt.Failure(e) => Attempt.failure(e)
|
||||
}
|
||||
def decode(buffer: BitVector): scodec.Attempt[scodec.DecodeResult[Vector[A]]] = {
|
||||
Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match {
|
||||
case Attempt.Successful(firstValue) =>
|
||||
Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match {
|
||||
case Attempt.Successful(secondValue) =>
|
||||
Attempt.successful(DecodeResult(firstValue.value ++ secondValue.value, secondValue.remainder))
|
||||
case Attempt.Failure(e) => Attempt.failure(e)
|
||||
}
|
||||
case Attempt.Failure(e) => Attempt.failure(e)
|
||||
}
|
||||
}
|
||||
|
||||
override def toString = s"vector($codec)"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.newcodecs
|
||||
|
||||
import scodec.{ Attempt, Codec, DecodeResult, Err, SizeBound }
|
||||
import scodec.bits.{ BitVector, ByteOrdering }
|
||||
import scodec.{Attempt, Codec, DecodeResult, Err, SizeBound}
|
||||
import scodec.bits.{BitVector, ByteOrdering}
|
||||
|
||||
final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Codec[Double] {
|
||||
|
||||
|
|
@ -14,14 +14,14 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
|
|||
|
||||
override def sizeBound = SizeBound.exact(bitsL)
|
||||
|
||||
def QuantizeDouble(value : Double) : Int = {
|
||||
val range : Double = max - min;
|
||||
def QuantizeDouble(value: Double): Int = {
|
||||
val range: Double = max - min;
|
||||
|
||||
if (range == 0.0)
|
||||
return 0
|
||||
|
||||
val bit_max : Int = 1 << bits;
|
||||
val rounded_quantized : Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt
|
||||
val bit_max: Int = 1 << bits;
|
||||
val rounded_quantized: Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt
|
||||
|
||||
if (rounded_quantized < 0)
|
||||
return 0
|
||||
|
|
@ -32,7 +32,7 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
|
|||
return rounded_quantized
|
||||
}
|
||||
|
||||
def UnquantizeDouble(value : Int) : Double = {
|
||||
def UnquantizeDouble(value: Int): Double = {
|
||||
return ((max - min) * value.toDouble / (1 << bitsL.toInt).toDouble + min)
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,9 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
|
|||
|
||||
override def decode(buffer: BitVector) = {
|
||||
if (buffer.sizeGreaterThanOrEqual(bitsL))
|
||||
Attempt.successful(DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL)))
|
||||
Attempt.successful(
|
||||
DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL))
|
||||
)
|
||||
else
|
||||
Attempt.failure(Err.insufficientBits(bitsL, buffer.size))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,23 +2,28 @@
|
|||
package net.psforever.newcodecs
|
||||
|
||||
import scodec.Attempt
|
||||
import scodec.Attempt.{Failure, Successful}
|
||||
import scodec._
|
||||
import scodec.bits.BitVector
|
||||
|
||||
package object newcodecs {
|
||||
def q_double(min: Double, max: Double, bits: Int): Codec[Double] = new QuantizedDoubleCodec(min, max, bits)
|
||||
|
||||
def q_float(min : Double, max : Double, bits : Int): Codec[Float] = q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
|
||||
def q_float(min: Double, max: Double, bits: Int): Codec[Float] =
|
||||
q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
|
||||
|
||||
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] = new BinaryChoiceCodec(choice, codec_true, codec_false)
|
||||
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] =
|
||||
new BinaryChoiceCodec(choice, codec_true, codec_false)
|
||||
|
||||
def prefixedVectorOfN[A](countCodec: Codec[Int], firstValueCodec: Codec[A], valueCodec: Codec[A]): Codec[Vector[A]] =
|
||||
countCodec.
|
||||
flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }.
|
||||
narrow[Vector[A]]({ case (cnt, xs) =>
|
||||
if (xs.size == cnt) Attempt.successful(xs)
|
||||
else Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
|
||||
}, xs => (xs.size, xs)).
|
||||
withToString(s"vectorOfN($countCodec, $valueCodec)")
|
||||
countCodec
|
||||
.flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }
|
||||
.narrow[Vector[A]](
|
||||
{
|
||||
case (cnt, xs) =>
|
||||
if (xs.size == cnt) Attempt.successful(xs)
|
||||
else
|
||||
Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
|
||||
},
|
||||
xs => (xs.size, xs)
|
||||
)
|
||||
.withToString(s"vectorOfN($countCodec, $valueCodec)")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects
|
||||
|
||||
class Account(private val accountId : Int, private val username : String, private val gm : Boolean = false) {
|
||||
def AccountId : Int = accountId
|
||||
def Username : String = username
|
||||
def GM : Boolean = gm
|
||||
class Account(private val accountId: Int, private val username: String, private val gm: Boolean = false) {
|
||||
def AccountId: Int = accountId
|
||||
def Username: String = username
|
||||
def GM: Boolean = gm
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,37 +5,36 @@ import net.psforever.objects.definition.AmmoBoxDefinition
|
|||
import net.psforever.objects.equipment.{Ammo, Equipment}
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
class AmmoBox(private val ammoDef : AmmoBoxDefinition,
|
||||
cap : Option[Int] = None
|
||||
) extends Equipment {
|
||||
private var capacity = if(cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) } else { FullCapacity }
|
||||
class AmmoBox(private val ammoDef: AmmoBoxDefinition, cap: Option[Int] = None) extends Equipment {
|
||||
private var capacity = if (cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) }
|
||||
else { FullCapacity }
|
||||
|
||||
def AmmoType : Ammo.Value = ammoDef.AmmoType
|
||||
def AmmoType: Ammo.Value = ammoDef.AmmoType
|
||||
|
||||
def Capacity : Int = capacity
|
||||
def Capacity: Int = capacity
|
||||
|
||||
def Capacity_=(toCapacity : Int) : Int = {
|
||||
def Capacity_=(toCapacity: Int): Int = {
|
||||
capacity = AmmoBox.limitCapacity(toCapacity)
|
||||
Capacity
|
||||
}
|
||||
|
||||
def FullCapacity : Int = ammoDef.Capacity
|
||||
def FullCapacity: Int = ammoDef.Capacity
|
||||
|
||||
def Definition : AmmoBoxDefinition = ammoDef
|
||||
def Definition: AmmoBoxDefinition = ammoDef
|
||||
|
||||
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction
|
||||
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
|
||||
|
||||
override def toString : String = {
|
||||
override def toString: String = {
|
||||
AmmoBox.toString(this)
|
||||
}
|
||||
}
|
||||
|
||||
object AmmoBox {
|
||||
def apply(ammoDef : AmmoBoxDefinition) : AmmoBox = {
|
||||
def apply(ammoDef: AmmoBoxDefinition): AmmoBox = {
|
||||
new AmmoBox(ammoDef)
|
||||
}
|
||||
|
||||
def apply(ammoDef : AmmoBoxDefinition, capacity : Int) : AmmoBox = {
|
||||
def apply(ammoDef: AmmoBoxDefinition, capacity: Int): AmmoBox = {
|
||||
new AmmoBox(ammoDef, Some(capacity))
|
||||
}
|
||||
|
||||
|
|
@ -48,25 +47,25 @@ object AmmoBox {
|
|||
* @param box an `AmmoBox` object of unspecified capacity
|
||||
* @return a `List` of `AmmoBox` objects with correct capacities
|
||||
*/
|
||||
def Split(box : AmmoBox) : List[AmmoBox] = {
|
||||
val ammoDef = box.Definition
|
||||
val boxCap : Int = box.Capacity
|
||||
val maxCap : Int = ammoDef.Capacity
|
||||
val splitCap : Int = boxCap / maxCap
|
||||
def Split(box: AmmoBox): List[AmmoBox] = {
|
||||
val ammoDef = box.Definition
|
||||
val boxCap: Int = box.Capacity
|
||||
val maxCap: Int = ammoDef.Capacity
|
||||
val splitCap: Int = boxCap / maxCap
|
||||
box.Capacity = math.min(box.Capacity, maxCap)
|
||||
val list : List[AmmoBox] = if(splitCap == 0) { Nil } else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) }
|
||||
val list: List[AmmoBox] = if (splitCap == 0) { Nil }
|
||||
else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) }
|
||||
val leftover = boxCap - maxCap * splitCap
|
||||
if(leftover > 0) {
|
||||
if (leftover > 0) {
|
||||
list :+ AmmoBox(ammoDef, leftover)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
def limitCapacity(count : Int, min : Int = 0) : Int = math.min(math.max(min, count), 65535)
|
||||
def limitCapacity(count: Int, min: Int = 0): Int = math.min(math.max(min, count), 65535)
|
||||
|
||||
def toString(obj : AmmoBox) : String = {
|
||||
def toString(obj: AmmoBox): String = {
|
||||
s"box of ${obj.AmmoType} ammo (${obj.Capacity})"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,28 @@ import net.psforever.types._
|
|||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
|
||||
class Avatar(private val char_id : Long, val name : String, val faction : PlanetSideEmpire.Value, val sex : CharacterGender.Value, val head : Int, val voice : CharacterVoice.Value) {
|
||||
class Avatar(
|
||||
private val char_id: Long,
|
||||
val name: String,
|
||||
val faction: PlanetSideEmpire.Value,
|
||||
val sex: CharacterGender.Value,
|
||||
val head: Int,
|
||||
val voice: CharacterVoice.Value
|
||||
) {
|
||||
|
||||
/** char_id, Character ID; a unique identifier corresponding to a database table row index */
|
||||
/** Battle Experience Points */
|
||||
private var bep : Long = 0
|
||||
private var bep: Long = 0
|
||||
|
||||
/** Command Experience Points */
|
||||
private var cep : Long = 0
|
||||
/** Cosmetics **/
|
||||
private var pStyle : Option[Cosmetics] = None
|
||||
private var cep: Long = 0
|
||||
|
||||
/** Cosmetics * */
|
||||
private var pStyle: Option[Cosmetics] = None
|
||||
|
||||
/** Certifications */
|
||||
private val certs : mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]()
|
||||
private val certs: mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]()
|
||||
|
||||
/** Implants<br>
|
||||
* Unlike other objects, all `ImplantSlot` objects are already built into the `Avatar`.
|
||||
* Additionally, implants do not have tightly-coupled "`Definition` objects" that explain a formal implant object.
|
||||
|
|
@ -28,53 +40,60 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* @see `ImplantSlot`
|
||||
* @see `DetailedCharacterData.implants`
|
||||
*/
|
||||
private val implants : Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
|
||||
private val implants: Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
|
||||
|
||||
/** Equipment Loadouts<br>
|
||||
* 0-9 are Infantry loadouts<br>
|
||||
* 10-14 are Vehicle loadouts
|
||||
*/
|
||||
private val equipmentLoadouts : LoadoutManager = new LoadoutManager(15)
|
||||
private val equipmentLoadouts: LoadoutManager = new LoadoutManager(15)
|
||||
|
||||
/**
|
||||
* Squad Loadouts
|
||||
*/
|
||||
private val squadLoadouts : LoadoutManager = new LoadoutManager(10)
|
||||
private val squadLoadouts: LoadoutManager = new LoadoutManager(10)
|
||||
|
||||
/** Locker */
|
||||
private val locker : LockerContainer = new LockerContainer() {
|
||||
override def toString : String = {
|
||||
private val locker: LockerContainer = new LockerContainer() {
|
||||
override def toString: String = {
|
||||
s"$name's ${Definition.Name}"
|
||||
}
|
||||
}
|
||||
|
||||
private val deployables : DeployableToolbox = new DeployableToolbox
|
||||
private val deployables: DeployableToolbox = new DeployableToolbox
|
||||
|
||||
private var firstTimeEvents : List[String] = List[String]()
|
||||
private var firstTimeEvents: List[String] = List[String]()
|
||||
|
||||
/**
|
||||
* Looking For Squad:<br>
|
||||
* Indicates both a player state and the text on the marquee under the player nameplate.
|
||||
* Should only be valid when the player is not in a squad.
|
||||
*/
|
||||
private var lfs : Boolean = false
|
||||
private var lfs: Boolean = false
|
||||
|
||||
private var vehicleOwned: Option[PlanetSideGUID] = None
|
||||
|
||||
private var vehicleOwned : Option[PlanetSideGUID] = None
|
||||
/** key - object id<br>
|
||||
* value - time last used (ms)
|
||||
* */
|
||||
private var lastUsedEquipmentTimes : mutable.LongMap[Long] = mutable.LongMap[Long]()
|
||||
*/
|
||||
private var lastUsedEquipmentTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
|
||||
|
||||
/** exo-suit times are sorted by `Enumeration` order, which was determined by packet process<br>
|
||||
* key - exo-suit id<br>
|
||||
* value - time last used (ms)
|
||||
* */
|
||||
private val lastUsedExoSuitTimes : Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L)
|
||||
*/
|
||||
private val lastUsedExoSuitTimes: Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L)
|
||||
|
||||
/** mechanized exo-suit times are sorted by subtype distinction, which was determined by packet process<br>
|
||||
* key - subtype id<br>
|
||||
* value - time last used (ms)
|
||||
* */
|
||||
private val lastUsedMaxExoSuitTimes : Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa
|
||||
*/
|
||||
private val lastUsedMaxExoSuitTimes: Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa
|
||||
/** key - object id<br>
|
||||
* value - time last acquired (from a terminal) (ms)
|
||||
* */
|
||||
private var lastPurchaseTimes : mutable.LongMap[Long] = mutable.LongMap[Long]()
|
||||
*/
|
||||
private var lastPurchaseTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
|
||||
|
||||
/**
|
||||
* To reload purchase and use timers, a string representing the item must be produced.
|
||||
* Point directly from the object id to the object definition and get the `Name` from that definition.
|
||||
|
|
@ -83,29 +102,29 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* key - object id<br>
|
||||
* value - most basic object definition information
|
||||
*/
|
||||
private val objectTypeNameReference : mutable.LongMap[String] = new mutable.LongMap[String]()
|
||||
private val objectTypeNameReference: mutable.LongMap[String] = new mutable.LongMap[String]()
|
||||
|
||||
def CharId : Long = char_id
|
||||
def CharId: Long = char_id
|
||||
|
||||
def BEP : Long = bep
|
||||
def BEP: Long = bep
|
||||
|
||||
def BEP_=(battleExperiencePoints : Long) : Long = {
|
||||
def BEP_=(battleExperiencePoints: Long): Long = {
|
||||
bep = math.max(0L, math.min(battleExperiencePoints, 4294967295L))
|
||||
BEP
|
||||
}
|
||||
|
||||
def Certifications : mutable.Set[CertificationType.Value] = certs
|
||||
def Certifications: mutable.Set[CertificationType.Value] = certs
|
||||
|
||||
def CEP : Long = cep
|
||||
def CEP: Long = cep
|
||||
|
||||
def CEP_=(commandExperiencePoints : Long) : Long = {
|
||||
def CEP_=(commandExperiencePoints: Long): Long = {
|
||||
cep = math.max(0L, math.min(commandExperiencePoints, 4294967295L))
|
||||
CEP
|
||||
}
|
||||
|
||||
def PersonalStyleFeatures : Option[Cosmetics] = pStyle
|
||||
def PersonalStyleFeatures: Option[Cosmetics] = pStyle
|
||||
|
||||
def PersonalStyleFeatures_=(app : Cosmetics) : Option[Cosmetics] = {
|
||||
def PersonalStyleFeatures_=(app: Cosmetics): Option[Cosmetics] = {
|
||||
pStyle = Some(app)
|
||||
pStyle
|
||||
}
|
||||
|
|
@ -114,7 +133,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* Retrieve the three implant slots for this player.
|
||||
* @return an `Array` of `ImplantSlot` objects
|
||||
*/
|
||||
def Implants : Array[ImplantSlot] = implants
|
||||
def Implants: Array[ImplantSlot] = implants
|
||||
|
||||
/**
|
||||
* What kind of implant is installed into the given slot number?
|
||||
|
|
@ -122,8 +141,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* @param slot the slot number
|
||||
* @return the tye of implant
|
||||
*/
|
||||
def Implant(slot : Int) : ImplantType.Value = {
|
||||
if(-1 < slot && slot < implants.length) { implants(slot).Implant } else { ImplantType.None }
|
||||
def Implant(slot: Int): ImplantType.Value = {
|
||||
if (-1 < slot && slot < implants.length) { implants(slot).Implant }
|
||||
else { ImplantType.None }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,8 +156,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* @param implant the implant being installed
|
||||
* @return the index of the `ImplantSlot` where the implant was installed
|
||||
*/
|
||||
def InstallImplant(implant : ImplantDefinition) : Option[Int] = {
|
||||
implants.find({p => p.Installed.contains(implant) || p.Implant == implant.Type}) match { //try to find the installed implant
|
||||
def InstallImplant(implant: ImplantDefinition): Option[Int] = {
|
||||
implants
|
||||
.find({ p => p.Installed.contains(implant) || p.Implant == implant.Type }) match { //try to find the installed implant
|
||||
case None =>
|
||||
recursiveFindImplantInSlot(implants.iterator, ImplantType.None) match { //install in a free slot
|
||||
case Some(slot) =>
|
||||
|
|
@ -164,7 +185,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* @param implantType the type of implant being uninstalled
|
||||
* @return the index of the `ImplantSlot` where the implant was found and uninstalled
|
||||
*/
|
||||
def UninstallImplant(implantType : ImplantType.Value) : Option[Int] = {
|
||||
def UninstallImplant(implantType: ImplantType.Value): Option[Int] = {
|
||||
recursiveFindImplantInSlot(implants.iterator, implantType) match {
|
||||
case Some(slot) =>
|
||||
implants(slot).Implant = None
|
||||
|
|
@ -183,22 +204,24 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
* @param index a defaulted index value representing the structure underlying the `Iterator` param
|
||||
* @return the index where the target implant is installed
|
||||
*/
|
||||
@tailrec private def recursiveFindImplantInSlot(iter : Iterator[ImplantSlot], implantType : ImplantType.Value, index : Int = 0) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursiveFindImplantInSlot(
|
||||
iter: Iterator[ImplantSlot],
|
||||
implantType: ImplantType.Value,
|
||||
index: Int = 0
|
||||
): Option[Int] = {
|
||||
if (!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val slot = iter.next
|
||||
if(slot.Unlocked && slot.Implant == implantType) {
|
||||
if (slot.Unlocked && slot.Implant == implantType) {
|
||||
Some(index)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
recursiveFindImplantInSlot(iter, implantType, index + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def ResetAllImplants() : Unit = {
|
||||
def ResetAllImplants(): Unit = {
|
||||
implants.foreach(slot => {
|
||||
slot.Installed match {
|
||||
case Some(_) =>
|
||||
|
|
@ -210,111 +233,110 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
})
|
||||
}
|
||||
|
||||
def EquipmentLoadouts : LoadoutManager = equipmentLoadouts
|
||||
def EquipmentLoadouts: LoadoutManager = equipmentLoadouts
|
||||
|
||||
def SquadLoadouts : LoadoutManager = squadLoadouts
|
||||
def SquadLoadouts: LoadoutManager = squadLoadouts
|
||||
|
||||
def Locker : LockerContainer = locker
|
||||
def Locker: LockerContainer = locker
|
||||
|
||||
def FifthSlot : EquipmentSlot = {
|
||||
def FifthSlot: EquipmentSlot = {
|
||||
new OffhandEquipmentSlot(EquipmentSize.Inventory) {
|
||||
val obj = new LockerEquipment(locker)
|
||||
Equipment = obj
|
||||
}
|
||||
}
|
||||
|
||||
def Deployables : DeployableToolbox = deployables
|
||||
def Deployables: DeployableToolbox = deployables
|
||||
|
||||
def FirstTimeEvents : List[String] = firstTimeEvents
|
||||
def FirstTimeEvents: List[String] = firstTimeEvents
|
||||
|
||||
def FirstTimeEvents_=(event : String) : List[String] = FirstTimeEvents_=(List(event))
|
||||
def FirstTimeEvents_=(event: String): List[String] = FirstTimeEvents_=(List(event))
|
||||
|
||||
def FirstTimeEvents_=(events : List[String]) : List[String] = {
|
||||
def FirstTimeEvents_=(events: List[String]): List[String] = {
|
||||
firstTimeEvents ++= events
|
||||
FirstTimeEvents
|
||||
}
|
||||
|
||||
def LFS : Boolean = lfs
|
||||
def LFS: Boolean = lfs
|
||||
|
||||
def LFS_=(looking : Boolean) : Boolean = {
|
||||
def LFS_=(looking: Boolean): Boolean = {
|
||||
lfs = looking
|
||||
LFS
|
||||
}
|
||||
|
||||
def VehicleOwned : Option[PlanetSideGUID] = vehicleOwned
|
||||
def VehicleOwned: Option[PlanetSideGUID] = vehicleOwned
|
||||
|
||||
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
|
||||
def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
|
||||
|
||||
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
vehicleOwned = guid
|
||||
VehicleOwned
|
||||
}
|
||||
|
||||
def GetLastUsedTime(code : Int) : Long = {
|
||||
def GetLastUsedTime(code: Int): Long = {
|
||||
lastUsedEquipmentTimes.get(code) match {
|
||||
case Some(time) => time
|
||||
case None => 0
|
||||
case None => 0
|
||||
}
|
||||
}
|
||||
|
||||
def GetLastUsedTime(code : ExoSuitType.Value) : Long = {
|
||||
def GetLastUsedTime(code: ExoSuitType.Value): Long = {
|
||||
lastUsedExoSuitTimes(code.id)
|
||||
}
|
||||
|
||||
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = {
|
||||
if(code == ExoSuitType.MAX) {
|
||||
def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = {
|
||||
if (code == ExoSuitType.MAX) {
|
||||
lastUsedMaxExoSuitTimes(subtype)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
GetLastUsedTime(code)
|
||||
}
|
||||
}
|
||||
|
||||
def GetAllLastUsedTimes : Map[Long, Long] = lastUsedEquipmentTimes.toMap
|
||||
def GetAllLastUsedTimes: Map[Long, Long] = lastUsedEquipmentTimes.toMap
|
||||
|
||||
def SetLastUsedTime(code : Int, time : Long) : Unit = {
|
||||
def SetLastUsedTime(code: Int, time: Long): Unit = {
|
||||
lastUsedEquipmentTimes += code.toLong -> time
|
||||
}
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value) : Unit = SetLastUsedTime(code, System.currentTimeMillis())
|
||||
def SetLastUsedTime(code: ExoSuitType.Value): Unit = SetLastUsedTime(code, System.currentTimeMillis())
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = {
|
||||
def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = {
|
||||
lastUsedExoSuitTimes(code.id) = time
|
||||
}
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = {
|
||||
if(code == ExoSuitType.MAX) {
|
||||
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit = {
|
||||
if (code == ExoSuitType.MAX) {
|
||||
lastUsedMaxExoSuitTimes(subtype) = time
|
||||
}
|
||||
SetLastUsedTime(code, time)
|
||||
}
|
||||
|
||||
def GetLastPurchaseTime(code : Int) : Long = {
|
||||
def GetLastPurchaseTime(code: Int): Long = {
|
||||
lastPurchaseTimes.get(code) match {
|
||||
case Some(time) => time
|
||||
case None => 0
|
||||
case None => 0
|
||||
}
|
||||
}
|
||||
|
||||
def GetAllLastPurchaseTimes : Map[Long, Long] = lastPurchaseTimes.toMap
|
||||
def GetAllLastPurchaseTimes: Map[Long, Long] = lastPurchaseTimes.toMap
|
||||
|
||||
def SetLastPurchaseTime(code : Int, time : Long) : Unit = {
|
||||
def SetLastPurchaseTime(code: Int, time: Long): Unit = {
|
||||
lastPurchaseTimes += code.toLong -> time
|
||||
}
|
||||
|
||||
def ObjectTypeNameReference(id : Long) : String = {
|
||||
def ObjectTypeNameReference(id: Long): String = {
|
||||
objectTypeNameReference.get(id) match {
|
||||
case Some(objectName) => objectName
|
||||
case None => ""
|
||||
case None => ""
|
||||
}
|
||||
}
|
||||
|
||||
def ObjectTypeNameReference(id : Long, name : String) : String = {
|
||||
def ObjectTypeNameReference(id: Long, name: String): String = {
|
||||
objectTypeNameReference(id) = name
|
||||
name
|
||||
}
|
||||
|
||||
def Definition : AvatarDefinition = GlobalDefinitions.avatar
|
||||
def Definition: AvatarDefinition = GlobalDefinitions.avatar
|
||||
|
||||
/*
|
||||
Merit Commendations and Ribbons
|
||||
|
|
@ -326,19 +348,20 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
|
||||
def canEqual(other: Any): Boolean = other.isInstanceOf[Avatar]
|
||||
|
||||
override def equals(other : Any) : Boolean = other match {
|
||||
case that: Avatar =>
|
||||
(that canEqual this) &&
|
||||
name == that.name &&
|
||||
faction == that.faction &&
|
||||
sex == that.sex &&
|
||||
head == that.head &&
|
||||
voice == that.voice
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
override def equals(other: Any): Boolean =
|
||||
other match {
|
||||
case that: Avatar =>
|
||||
(that canEqual this) &&
|
||||
name == that.name &&
|
||||
faction == that.faction &&
|
||||
sex == that.sex &&
|
||||
head == that.head &&
|
||||
voice == that.voice
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
override def hashCode() : Int = {
|
||||
override def hashCode(): Int = {
|
||||
val state = Seq(name, faction, sex, head, voice)
|
||||
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
|
||||
}
|
||||
|
|
@ -347,9 +370,15 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
|
|||
}
|
||||
|
||||
object Avatar {
|
||||
def apply(name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : CharacterVoice.Value) : Avatar = {
|
||||
def apply(
|
||||
name: String,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
sex: CharacterGender.Value,
|
||||
head: Int,
|
||||
voice: CharacterVoice.Value
|
||||
): Avatar = {
|
||||
new Avatar(0L, name, faction, sex, head, voice)
|
||||
}
|
||||
|
||||
def toString(avatar : Avatar) : String = s"${avatar.faction} ${avatar.name}"
|
||||
def toString(avatar: Avatar): String = s"${avatar.faction} ${avatar.name}"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
// Copyright (c) 2017 PSForever
|
||||
package net.psforever.objects
|
||||
|
||||
class BoomerDeployable(cdef : ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) {
|
||||
private var trigger : Option[BoomerTrigger] = None
|
||||
class BoomerDeployable(cdef: ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) {
|
||||
private var trigger: Option[BoomerTrigger] = None
|
||||
|
||||
def Trigger : Option[BoomerTrigger] = trigger
|
||||
def Trigger: Option[BoomerTrigger] = trigger
|
||||
|
||||
def Trigger_=(item : BoomerTrigger) : Option[BoomerTrigger] = {
|
||||
if(trigger.isEmpty) { //can only set trigger once
|
||||
def Trigger_=(item: BoomerTrigger): Option[BoomerTrigger] = {
|
||||
if (trigger.isEmpty) { //can only set trigger once
|
||||
trigger = Some(item)
|
||||
}
|
||||
Trigger
|
||||
}
|
||||
|
||||
def Trigger_=(item : Option[BoomerTrigger]) : Option[BoomerTrigger] = {
|
||||
if(item.isEmpty) {
|
||||
def Trigger_=(item: Option[BoomerTrigger]): Option[BoomerTrigger] = {
|
||||
if (item.isEmpty) {
|
||||
trigger = None
|
||||
}
|
||||
Trigger
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ import net.psforever.objects.equipment.RemoteUnit
|
|||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
class BoomerTrigger extends SimpleItem(GlobalDefinitions.boomer_trigger) with RemoteUnit {
|
||||
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction
|
||||
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,47 +20,48 @@ import net.psforever.types.CertificationType
|
|||
* indicate whether the current output product is something the player is permitted to utilize.
|
||||
* @param cItemDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
|
||||
*/
|
||||
class ConstructionItem(private val cItemDef : ConstructionItemDefinition) extends Equipment
|
||||
with FireModeSwitch[ConstructionFireMode] {
|
||||
private var fireModeIndex : Int = 0
|
||||
private var ammoTypeIndex : Int = 0
|
||||
class ConstructionItem(private val cItemDef: ConstructionItemDefinition)
|
||||
extends Equipment
|
||||
with FireModeSwitch[ConstructionFireMode] {
|
||||
private var fireModeIndex: Int = 0
|
||||
private var ammoTypeIndex: Int = 0
|
||||
|
||||
def FireModeIndex : Int = fireModeIndex
|
||||
def FireModeIndex: Int = fireModeIndex
|
||||
|
||||
def FireModeIndex_=(index : Int) : Int = {
|
||||
def FireModeIndex_=(index: Int): Int = {
|
||||
fireModeIndex = index % Definition.Modes.length
|
||||
FireModeIndex
|
||||
}
|
||||
|
||||
def FireMode : ConstructionFireMode = Definition.Modes(fireModeIndex)
|
||||
def FireMode: ConstructionFireMode = Definition.Modes(fireModeIndex)
|
||||
|
||||
def NextFireMode : ConstructionFireMode = {
|
||||
def NextFireMode: ConstructionFireMode = {
|
||||
FireModeIndex = FireModeIndex + 1
|
||||
ammoTypeIndex = 0
|
||||
FireMode
|
||||
}
|
||||
|
||||
def AmmoTypeIndex : Int = ammoTypeIndex
|
||||
def AmmoTypeIndex: Int = ammoTypeIndex
|
||||
|
||||
def AmmoTypeIndex_=(index : Int) : Int = {
|
||||
def AmmoTypeIndex_=(index: Int): Int = {
|
||||
ammoTypeIndex = index % FireMode.Deployables.length
|
||||
AmmoTypeIndex
|
||||
}
|
||||
|
||||
def AmmoType : DeployedItem.Value = FireMode.Deployables(ammoTypeIndex)
|
||||
def AmmoType: DeployedItem.Value = FireMode.Deployables(ammoTypeIndex)
|
||||
|
||||
def NextAmmoType : DeployedItem.Value = {
|
||||
def NextAmmoType: DeployedItem.Value = {
|
||||
AmmoTypeIndex = AmmoTypeIndex + 1
|
||||
FireMode.Deployables(ammoTypeIndex)
|
||||
}
|
||||
|
||||
def ModePermissions : Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex)
|
||||
def ModePermissions: Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex)
|
||||
|
||||
def Definition : ConstructionItemDefinition = cItemDef
|
||||
def Definition: ConstructionItemDefinition = cItemDef
|
||||
}
|
||||
|
||||
object ConstructionItem {
|
||||
def apply(cItemDef : ConstructionItemDefinition) : ConstructionItem = {
|
||||
def apply(cItemDef: ConstructionItemDefinition): ConstructionItem = {
|
||||
new ConstructionItem(cItemDef)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,20 +5,21 @@ object Default {
|
|||
//cancellable
|
||||
import akka.actor.Cancellable
|
||||
protected class InternalCancellable extends Cancellable {
|
||||
override def cancel : Boolean = true
|
||||
override def isCancelled : Boolean = true
|
||||
override def cancel: Boolean = true
|
||||
override def isCancelled: Boolean = true
|
||||
}
|
||||
private val cancellable : Cancellable = new InternalCancellable
|
||||
private val cancellable: Cancellable = new InternalCancellable
|
||||
|
||||
/**
|
||||
* Used to initialize the value of a re-usable `Cancellable` object.
|
||||
* By convention, it always acts like it has been cancelled before and can be cancelled.
|
||||
* Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
|
||||
*/
|
||||
final def Cancellable : Cancellable = cancellable
|
||||
final def Cancellable: Cancellable = cancellable
|
||||
|
||||
//actor
|
||||
import akka.actor.{Actor => AkkaActor, ActorRef, ActorSystem, DeadLetter, Props}
|
||||
|
||||
/**
|
||||
* An actor designed to wrap around `deadLetters` and redirect all normal messages to it.
|
||||
* This measure is more to "protect" `deadLetters` than anything else.
|
||||
|
|
@ -26,22 +27,23 @@ object Default {
|
|||
* The original target to which the actor is assigned will not be implicitly accredited.
|
||||
*/
|
||||
private class DefaultActor extends AkkaActor {
|
||||
def receive : Receive = {
|
||||
def receive: Receive = {
|
||||
case msg => context.system.deadLetters ! DeadLetter(msg, sender, self)
|
||||
}
|
||||
}
|
||||
private var defaultRef : ActorRef = ActorRef.noSender
|
||||
private var defaultRef: ActorRef = ActorRef.noSender
|
||||
|
||||
/**
|
||||
* Instigate the default actor.
|
||||
* @param sys the actor universe under which this default actor will exist
|
||||
* @return the new default actor
|
||||
*/
|
||||
def apply(sys : ActorSystem) : ActorRef = {
|
||||
if(defaultRef == ActorRef.noSender) {
|
||||
def apply(sys: ActorSystem): ActorRef = {
|
||||
if (defaultRef == ActorRef.noSender) {
|
||||
defaultRef = sys.actorOf(Props[DefaultActor], name = s"system-default-actor")
|
||||
}
|
||||
defaultRef
|
||||
}
|
||||
|
||||
final def Actor : ActorRef = defaultRef
|
||||
final def Actor: ActorRef = defaultRef
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,26 +16,36 @@ object Deployables {
|
|||
private val log = org.log4s.getLogger("Deployables")
|
||||
|
||||
object Make {
|
||||
def apply(item : DeployedItem.Value) : ()=>PlanetSideGameObject with Deployable = cemap(item)
|
||||
def apply(item: DeployedItem.Value): () => PlanetSideGameObject with Deployable = cemap(item)
|
||||
|
||||
private val cemap : Map[DeployedItem.Value, ()=>PlanetSideGameObject with Deployable] = Map(
|
||||
DeployedItem.boomer -> { ()=> new BoomerDeployable(GlobalDefinitions.boomer) },
|
||||
DeployedItem.he_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.he_mine) },
|
||||
DeployedItem.jammer_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.jammer_mine) },
|
||||
DeployedItem.spitfire_turret -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_turret) },
|
||||
DeployedItem.spitfire_cloaked -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_cloaked) },
|
||||
DeployedItem.spitfire_aa -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_aa) },
|
||||
DeployedItem.motionalarmsensor -> { ()=> new SensorDeployable(GlobalDefinitions.motionalarmsensor) },
|
||||
DeployedItem.sensor_shield -> { ()=> new SensorDeployable(GlobalDefinitions.sensor_shield) },
|
||||
DeployedItem.tank_traps -> { ()=> new TrapDeployable(GlobalDefinitions.tank_traps) },
|
||||
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
|
||||
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
|
||||
DeployedItem.portable_manned_turret_nc -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc) },
|
||||
DeployedItem.portable_manned_turret_tr -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) },
|
||||
DeployedItem.portable_manned_turret_vs -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs) },
|
||||
DeployedItem.deployable_shield_generator -> { ()=> new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator) },
|
||||
DeployedItem.router_telepad_deployable -> { () => new TelepadDeployable(GlobalDefinitions.router_telepad_deployable) }
|
||||
).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } )
|
||||
private val cemap: Map[DeployedItem.Value, () => PlanetSideGameObject with Deployable] = Map(
|
||||
DeployedItem.boomer -> { () => new BoomerDeployable(GlobalDefinitions.boomer) },
|
||||
DeployedItem.he_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.he_mine) },
|
||||
DeployedItem.jammer_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.jammer_mine) },
|
||||
DeployedItem.spitfire_turret -> { () => new TurretDeployable(GlobalDefinitions.spitfire_turret) },
|
||||
DeployedItem.spitfire_cloaked -> { () => new TurretDeployable(GlobalDefinitions.spitfire_cloaked) },
|
||||
DeployedItem.spitfire_aa -> { () => new TurretDeployable(GlobalDefinitions.spitfire_aa) },
|
||||
DeployedItem.motionalarmsensor -> { () => new SensorDeployable(GlobalDefinitions.motionalarmsensor) },
|
||||
DeployedItem.sensor_shield -> { () => new SensorDeployable(GlobalDefinitions.sensor_shield) },
|
||||
DeployedItem.tank_traps -> { () => new TrapDeployable(GlobalDefinitions.tank_traps) },
|
||||
DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
|
||||
DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
|
||||
DeployedItem.portable_manned_turret_nc -> { () =>
|
||||
new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc)
|
||||
},
|
||||
DeployedItem.portable_manned_turret_tr -> { () =>
|
||||
new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr)
|
||||
},
|
||||
DeployedItem.portable_manned_turret_vs -> { () =>
|
||||
new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
|
||||
},
|
||||
DeployedItem.deployable_shield_generator -> { () =>
|
||||
new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
|
||||
},
|
||||
DeployedItem.router_telepad_deployable -> { () =>
|
||||
new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
|
||||
}
|
||||
).withDefaultValue({ () => new ExplosiveDeployable(GlobalDefinitions.boomer) })
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -60,7 +70,7 @@ object Deployables {
|
|||
* @param time length of time that the deployable is allowed to exist in the game world;
|
||||
* `None` indicates the normal un-owned existence time (180 seconds)
|
||||
*/
|
||||
def AnnounceDestroyDeployable(target : PlanetSideGameObject with Deployable, time : Option[FiniteDuration]) : Unit = {
|
||||
def AnnounceDestroyDeployable(target: PlanetSideGameObject with Deployable, time: Option[FiniteDuration]): Unit = {
|
||||
val zone = target.Zone
|
||||
target.OwnerName match {
|
||||
case Some(owner) =>
|
||||
|
|
@ -68,10 +78,13 @@ object Deployables {
|
|||
zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target))
|
||||
case None => ;
|
||||
}
|
||||
zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon(
|
||||
PlanetSideGUID(0),
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0)))
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
s"${target.Faction}",
|
||||
LocalAction.DeployableMapIcon(
|
||||
PlanetSideGUID(0),
|
||||
DeploymentAction.Dismiss,
|
||||
DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))
|
||||
)
|
||||
)
|
||||
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone))
|
||||
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time))
|
||||
|
|
@ -86,17 +99,22 @@ object Deployables {
|
|||
* @return all previously-owned deployables after they have been processed;
|
||||
* boomers are listed before all other deployable types
|
||||
*/
|
||||
def Disown(zone : Zone, avatar : Avatar, replyTo : ActorRef) : List[PlanetSideGameObject with Deployable] = {
|
||||
def Disown(zone: Zone, avatar: Avatar, replyTo: ActorRef): List[PlanetSideGameObject with Deployable] = {
|
||||
val (boomers, deployables) =
|
||||
avatar.Deployables.Clear()
|
||||
avatar.Deployables
|
||||
.Clear()
|
||||
.map(zone.GUID)
|
||||
.collect { case Some(obj) => obj.asInstanceOf[PlanetSideGameObject with Deployable] }
|
||||
.partition(_.isInstanceOf[BoomerDeployable])
|
||||
//do not change the OwnerName field at this time
|
||||
boomers.collect({ case obj : BoomerDeployable =>
|
||||
zone.LocalEvents.tell(LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))), replyTo) //near-instant
|
||||
obj.Owner = None
|
||||
obj.Trigger = None
|
||||
boomers.collect({
|
||||
case obj: BoomerDeployable =>
|
||||
zone.LocalEvents.tell(
|
||||
LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))),
|
||||
replyTo
|
||||
) //near-instant
|
||||
obj.Owner = None
|
||||
obj.Trigger = None
|
||||
})
|
||||
deployables.foreach(obj => {
|
||||
zone.LocalEvents.tell(LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone)), replyTo) //normal decay
|
||||
|
|
@ -105,17 +123,17 @@ object Deployables {
|
|||
boomers ++ deployables
|
||||
}
|
||||
|
||||
def RemoveTelepad(vehicle: Vehicle) : Unit = {
|
||||
def RemoveTelepad(vehicle: Vehicle): Unit = {
|
||||
val zone = vehicle.Zone
|
||||
(vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||
case Some(util : Utility.InternalTelepad) =>
|
||||
case Some(util: Utility.InternalTelepad) =>
|
||||
val telepad = util.Telepad
|
||||
util.Telepad = None
|
||||
zone.GUID(telepad)
|
||||
case _ =>
|
||||
None
|
||||
}) match {
|
||||
case Some(telepad : TelepadDeployable) =>
|
||||
case Some(telepad: TelepadDeployable) =>
|
||||
log.info(s"BeforeUnload: deconstructing telepad $telepad that was linked to router $vehicle ...")
|
||||
telepad.Active = false
|
||||
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), zone))
|
||||
|
|
@ -124,13 +142,11 @@ object Deployables {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the deployables backend information.
|
||||
* @param avatar the player's core
|
||||
*/
|
||||
def InitializeDeployableQuantities(avatar : Avatar) : Boolean = {
|
||||
def InitializeDeployableQuantities(avatar: Avatar): Boolean = {
|
||||
log.info("Setting up combat engineering ...")
|
||||
avatar.Deployables.Initialize(avatar.Certifications.toSet)
|
||||
}
|
||||
|
|
@ -139,7 +155,7 @@ object Deployables {
|
|||
* Initialize the UI elements for deployables.
|
||||
* @param avatar the player's core
|
||||
*/
|
||||
def InitializeDeployableUIElements(avatar : Avatar) : List[(Int,Int,Int,Int)] = {
|
||||
def InitializeDeployableUIElements(avatar: Avatar): List[(Int, Int, Int, Int)] = {
|
||||
log.info("Setting up combat engineering UI ...")
|
||||
avatar.Deployables.UpdateUI()
|
||||
}
|
||||
|
|
@ -151,7 +167,11 @@ object Deployables {
|
|||
* @param certification the certification that was added
|
||||
* @param certificationSet all applicable certifications
|
||||
*/
|
||||
def AddToDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
|
||||
def AddToDeployableQuantities(
|
||||
avatar: Avatar,
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): List[(Int, Int, Int, Int)] = {
|
||||
avatar.Deployables.AddToDeployableQuantities(certification, certificationSet)
|
||||
avatar.Deployables.UpdateUI(certification)
|
||||
}
|
||||
|
|
@ -163,7 +183,11 @@ object Deployables {
|
|||
* @param certification the certification that was added
|
||||
* @param certificationSet all applicable certifications
|
||||
*/
|
||||
def RemoveFromDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
|
||||
def RemoveFromDeployableQuantities(
|
||||
avatar: Avatar,
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): List[(Int, Int, Int, Int)] = {
|
||||
avatar.Deployables.RemoveFromDeployableQuantities(certification, certificationSet)
|
||||
avatar.Deployables.UpdateUI(certification)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,61 +18,60 @@ import services.local.{LocalAction, LocalServiceMessage}
|
|||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class ExplosiveDeployable(cdef : ExplosiveDeployableDefinition) extends ComplexDeployable(cdef)
|
||||
with JammableUnit {
|
||||
class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) with JammableUnit {
|
||||
|
||||
override def Definition : ExplosiveDeployableDefinition = cdef
|
||||
override def Definition: ExplosiveDeployableDefinition = cdef
|
||||
}
|
||||
|
||||
class ExplosiveDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) {
|
||||
class ExplosiveDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
|
||||
Name = "explosive_deployable"
|
||||
DeployCategory = DeployableCategory.Mines
|
||||
Model = StandardResolutions.SimpleDeployables
|
||||
Packet = new SmallDeployableConverter
|
||||
|
||||
private var detonateOnJamming : Boolean = true
|
||||
private var detonateOnJamming: Boolean = true
|
||||
|
||||
def DetonateOnJamming : Boolean = detonateOnJamming
|
||||
def DetonateOnJamming: Boolean = detonateOnJamming
|
||||
|
||||
def DetonateOnJamming_=(detonate : Boolean) : Boolean = {
|
||||
def DetonateOnJamming_=(detonate: Boolean): Boolean = {
|
||||
detonateOnJamming = detonate
|
||||
DetonateOnJamming
|
||||
}
|
||||
|
||||
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
obj.Actor = context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
obj.Actor =
|
||||
context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
|
||||
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
|
||||
object ExplosiveDeployableDefinition {
|
||||
def apply(dtype : DeployedItem.Value) : ExplosiveDeployableDefinition = {
|
||||
def apply(dtype: DeployedItem.Value): ExplosiveDeployableDefinition = {
|
||||
new ExplosiveDeployableDefinition(dtype.id)
|
||||
}
|
||||
}
|
||||
|
||||
class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor
|
||||
with Damageable {
|
||||
class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with Damageable {
|
||||
def DamageableObject = mine
|
||||
|
||||
def receive : Receive = takesDamage
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def receive: Receive =
|
||||
takesDamage
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
protected def TakesDamage : Receive = {
|
||||
protected def TakesDamage: Receive = {
|
||||
case Vitality.Damage(applyDamageTo) =>
|
||||
if(mine.CanDamage) {
|
||||
if (mine.CanDamage) {
|
||||
val originalHealth = mine.Health
|
||||
val cause = applyDamageTo(mine)
|
||||
val damage = originalHealth - mine.Health
|
||||
if(Damageable.CanDamageOrJammer(mine, damage, cause)) {
|
||||
val cause = applyDamageTo(mine)
|
||||
val damage = originalHealth - mine.Health
|
||||
if (Damageable.CanDamageOrJammer(mine, damage, cause)) {
|
||||
ExplosiveDeployableControl.DamageResolution(mine, cause, damage)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mine.Health = originalHealth
|
||||
}
|
||||
}
|
||||
|
|
@ -80,17 +79,18 @@ class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor
|
|||
}
|
||||
|
||||
object ExplosiveDeployableControl {
|
||||
def DamageResolution(target : ExplosiveDeployable, cause : ResolvedProjectile, damage : Int) : Unit = {
|
||||
def DamageResolution(target: ExplosiveDeployable, cause: ResolvedProjectile, damage: Int): Unit = {
|
||||
target.History(cause)
|
||||
if(target.Health == 0) {
|
||||
if (target.Health == 0) {
|
||||
DestructionAwareness(target, cause)
|
||||
}
|
||||
else if(!target.Jammed && Damageable.CanJammer(target, cause)) {
|
||||
if(target.Jammed = {
|
||||
val radius = cause.projectile.profile.DamageRadius
|
||||
Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius
|
||||
}) {
|
||||
if(target.Definition.DetonateOnJamming) {
|
||||
} else if (!target.Jammed && Damageable.CanJammer(target, cause)) {
|
||||
if (
|
||||
target.Jammed = {
|
||||
val radius = cause.projectile.profile.DamageRadius
|
||||
Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius
|
||||
}
|
||||
) {
|
||||
if (target.Definition.DetonateOnJamming) {
|
||||
val zone = target.Zone
|
||||
zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.Detonate(target.GUID, target))
|
||||
|
|
@ -105,17 +105,23 @@ object ExplosiveDeployableControl {
|
|||
* @param target na
|
||||
* @param cause na
|
||||
*/
|
||||
def DestructionAwareness(target : ExplosiveDeployable, cause : ResolvedProjectile) : Unit = {
|
||||
def DestructionAwareness(target: ExplosiveDeployable, cause: ResolvedProjectile): Unit = {
|
||||
val zone = target.Zone
|
||||
val attribution = zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
|
||||
case Some(player) => player.GUID
|
||||
case _ => PlanetSideGUID(0)
|
||||
case _ => PlanetSideGUID(0)
|
||||
}
|
||||
target.Destroyed = true
|
||||
Deployables.AnnounceDestroyDeployable(target, Some(if(target.Jammed) 0 seconds else 500 milliseconds))
|
||||
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position))
|
||||
if(target.Health == 0) {
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID))
|
||||
Deployables.AnnounceDestroyDeployable(target, Some(if (target.Jammed) 0 seconds else 500 milliseconds))
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.Id,
|
||||
AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
|
||||
)
|
||||
if (target.Health == 0) {
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.Id,
|
||||
LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -14,61 +14,68 @@ import net.psforever.types.{ExoSuitType, ImplantType}
|
|||
* Being jammed de-activates the implant, put it into a state of "not being ready," and causes the initialization to repeat.
|
||||
*/
|
||||
class ImplantSlot {
|
||||
|
||||
/** is this slot available for holding an implant */
|
||||
private var unlocked : Boolean = false
|
||||
private var unlocked: Boolean = false
|
||||
|
||||
/** whether this implant is ready for use */
|
||||
private var initialized : Boolean = false
|
||||
/** */
|
||||
private var initializeTime : Long = 0L
|
||||
private var initialized: Boolean = false
|
||||
|
||||
/**
|
||||
*/
|
||||
private var initializeTime: Long = 0L
|
||||
|
||||
/** is this implant active */
|
||||
private var active : Boolean = false
|
||||
private var active: Boolean = false
|
||||
|
||||
/** what implant is currently installed in this slot; None if there is no implant currently installed */
|
||||
private var implant : Option[ImplantDefinition] = None
|
||||
private var implant: Option[ImplantDefinition] = None
|
||||
|
||||
def InitializeTime : Long = initializeTime
|
||||
def InitializeTime: Long = initializeTime
|
||||
|
||||
def InitializeTime_=(time : Long) : Long = {
|
||||
def InitializeTime_=(time: Long): Long = {
|
||||
initializeTime = time
|
||||
InitializeTime
|
||||
}
|
||||
|
||||
def Unlocked : Boolean = unlocked
|
||||
def Unlocked: Boolean = unlocked
|
||||
|
||||
def Unlocked_=(lock : Boolean) : Boolean = {
|
||||
def Unlocked_=(lock: Boolean): Boolean = {
|
||||
unlocked = lock || unlocked //do not let re-lock
|
||||
Unlocked
|
||||
}
|
||||
|
||||
def Initialized : Boolean = initialized
|
||||
def Initialized: Boolean = initialized
|
||||
|
||||
def Initialized_=(init : Boolean) : Boolean = {
|
||||
def Initialized_=(init: Boolean): Boolean = {
|
||||
initialized = Installed.isDefined && init
|
||||
Active = Active && initialized //can not be active just yet
|
||||
Initialized
|
||||
}
|
||||
|
||||
def Active : Boolean = active
|
||||
def Active: Boolean = active
|
||||
|
||||
def Active_=(state : Boolean) : Boolean = {
|
||||
def Active_=(state: Boolean): Boolean = {
|
||||
active = Initialized && state
|
||||
Active
|
||||
}
|
||||
|
||||
def Implant : ImplantType.Value = Installed match {
|
||||
case Some(idef) =>
|
||||
idef.Type
|
||||
case None =>
|
||||
Active = false
|
||||
Initialized = false
|
||||
ImplantType.None
|
||||
}
|
||||
def Implant: ImplantType.Value =
|
||||
Installed match {
|
||||
case Some(idef) =>
|
||||
idef.Type
|
||||
case None =>
|
||||
Active = false
|
||||
Initialized = false
|
||||
ImplantType.None
|
||||
}
|
||||
|
||||
def Implant_=(anImplant : ImplantDefinition) : ImplantType.Value = {
|
||||
def Implant_=(anImplant: ImplantDefinition): ImplantType.Value = {
|
||||
Implant_=(Some(anImplant))
|
||||
}
|
||||
|
||||
def Implant_=(anImplant : Option[ImplantDefinition]) : ImplantType.Value = {
|
||||
if(Unlocked) {
|
||||
def Implant_=(anImplant: Option[ImplantDefinition]): ImplantType.Value = {
|
||||
if (Unlocked) {
|
||||
anImplant match {
|
||||
case Some(_) =>
|
||||
implant = anImplant
|
||||
|
|
@ -81,20 +88,20 @@ class ImplantSlot {
|
|||
Implant
|
||||
}
|
||||
|
||||
def Installed : Option[ImplantDefinition] = implant
|
||||
def Installed: Option[ImplantDefinition] = implant
|
||||
|
||||
def MaxTimer : Long = Implant match {
|
||||
case ImplantType.None =>
|
||||
-1L
|
||||
case _ =>
|
||||
Installed.get.InitializationDuration
|
||||
}
|
||||
|
||||
def ActivationCharge : Int = {
|
||||
if(Active) {
|
||||
Installed.get.ActivationStaminaCost
|
||||
def MaxTimer: Long =
|
||||
Implant match {
|
||||
case ImplantType.None =>
|
||||
-1L
|
||||
case _ =>
|
||||
Installed.get.InitializationDuration
|
||||
}
|
||||
else {
|
||||
|
||||
def ActivationCharge: Int = {
|
||||
if (Active) {
|
||||
Installed.get.ActivationStaminaCost
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
@ -104,24 +111,23 @@ class ImplantSlot {
|
|||
* @param suit the exo-suit being worn
|
||||
* @return the amount of stamina (energy) that is consumed
|
||||
*/
|
||||
def Charge(suit : ExoSuitType.Value) : Int = {
|
||||
if(Active) {
|
||||
def Charge(suit: ExoSuitType.Value): Int = {
|
||||
if (Active) {
|
||||
val inst = Installed.get
|
||||
inst.StaminaCost
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
def Jammed() : Unit = {
|
||||
def Jammed(): Unit = {
|
||||
Active = false
|
||||
Initialized = false
|
||||
}
|
||||
}
|
||||
|
||||
object ImplantSlot {
|
||||
def apply() : ImplantSlot = {
|
||||
def apply(): ImplantSlot = {
|
||||
new ImplantSlot()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import net.psforever.objects.equipment.Equipment
|
|||
* A one-time-use recovery item that can be applied by the player while held within their inventory.
|
||||
* @param kitDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
|
||||
*/
|
||||
class Kit(private val kitDef : KitDefinition) extends Equipment {
|
||||
def Definition : KitDefinition = kitDef
|
||||
class Kit(private val kitDef: KitDefinition) extends Equipment {
|
||||
def Definition: KitDefinition = kitDef
|
||||
}
|
||||
|
||||
object Kit {
|
||||
def apply(kitDef : KitDefinition) : Kit = {
|
||||
def apply(kitDef: KitDefinition): Kit = {
|
||||
new Kit(kitDef)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,15 @@ import scala.collection.concurrent.{Map, TrieMap}
|
|||
* `LivePlayerList` is a singleton and this private class lacks exposure.
|
||||
*/
|
||||
private class LivePlayerList {
|
||||
/** key - the session id; value - a `Player` object */
|
||||
private val sessionMap : Map[Long, Avatar] = new TrieMap[Long, Avatar]
|
||||
|
||||
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = {
|
||||
/** key - the session id; value - a `Player` object */
|
||||
private val sessionMap: Map[Long, Avatar] = new TrieMap[Long, Avatar]
|
||||
|
||||
def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = {
|
||||
sessionMap.filter(predicate).values.toList
|
||||
}
|
||||
|
||||
def Add(sessionId : Long, avatar : Avatar) : Boolean = {
|
||||
def Add(sessionId: Long, avatar: Avatar): Boolean = {
|
||||
sessionMap.values.find(char => char.equals(avatar)) match {
|
||||
case None =>
|
||||
sessionMap.putIfAbsent(sessionId, avatar).isEmpty
|
||||
|
|
@ -24,11 +25,11 @@ private class LivePlayerList {
|
|||
}
|
||||
}
|
||||
|
||||
def Remove(sessionId : Long) : Option[Avatar] = {
|
||||
def Remove(sessionId: Long): Option[Avatar] = {
|
||||
sessionMap.remove(sessionId)
|
||||
}
|
||||
|
||||
def Shutdown : List[Avatar] = {
|
||||
def Shutdown: List[Avatar] = {
|
||||
val list = sessionMap.values.toList
|
||||
sessionMap.clear
|
||||
list
|
||||
|
|
@ -48,8 +49,9 @@ private class LivePlayerList {
|
|||
* `LivePlayerList.Remove(session)`
|
||||
*/
|
||||
object LivePlayerList {
|
||||
|
||||
/** As `LivePlayerList` is a singleton, an object of `LivePlayerList` is automatically instantiated. */
|
||||
private val Instance : LivePlayerList = new LivePlayerList
|
||||
private val Instance: LivePlayerList = new LivePlayerList
|
||||
|
||||
/**
|
||||
* Given some criteria, examine the mapping of user characters and find the ones that fulfill the requirements.<br>
|
||||
|
|
@ -61,7 +63,7 @@ object LivePlayerList {
|
|||
* @param predicate the conditions for filtering the live `Player`s
|
||||
* @return a list of users's `Player`s that fit the criteria
|
||||
*/
|
||||
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = Instance.WorldPopulation(predicate)
|
||||
def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = Instance.WorldPopulation(predicate)
|
||||
|
||||
/**
|
||||
* Create a mapped entry between the user's session and a user's character.
|
||||
|
|
@ -70,7 +72,7 @@ object LivePlayerList {
|
|||
* @param avatar the character
|
||||
* @return `true`, if the session was association was made; `false`, otherwise
|
||||
*/
|
||||
def Add(sessionId : Long, avatar : Avatar) : Boolean = Instance.Add(sessionId, avatar)
|
||||
def Add(sessionId: Long, avatar: Avatar): Boolean = Instance.Add(sessionId, avatar)
|
||||
|
||||
/**
|
||||
* Remove all entries related to the given session identifier from the mappings.
|
||||
|
|
@ -78,11 +80,11 @@ object LivePlayerList {
|
|||
* @param sessionId the session
|
||||
* @return any character that was afffected by the mapping removal
|
||||
*/
|
||||
def Remove(sessionId : Long) : Option[Avatar] = Instance.Remove(sessionId)
|
||||
def Remove(sessionId: Long): Option[Avatar] = Instance.Remove(sessionId)
|
||||
|
||||
/**
|
||||
* Hastily remove all mappings and ids.
|
||||
* @return an unsorted list of the characters that were still online
|
||||
*/
|
||||
def Shutdown : List[Avatar] = Instance.Shutdown
|
||||
def Shutdown: List[Avatar] = Instance.Shutdown
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ object LocalProjectile {
|
|||
* @param context a context to allow the object to properly set up `ActorSystem` functionality
|
||||
* @return the `LocalProjectile` object
|
||||
*/
|
||||
def Constructor(id : Int, context : ActorContext) : LocalProjectile = {
|
||||
def Constructor(id: Int, context: ActorContext): LocalProjectile = {
|
||||
new LocalProjectile()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,62 +19,60 @@ import services.avatar.{AvatarAction, AvatarServiceMessage}
|
|||
* The `Player` class refers to it as the "fifth slot" as its permanent slot number is encoded as `0x85`.
|
||||
* The inventory of this object is accessed using a game world `Locker` object (`mb_locker`).
|
||||
*/
|
||||
class LockerContainer extends PlanetSideServerObject
|
||||
with Container {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private val inventory = GridInventory(30, 20)
|
||||
class LockerContainer extends PlanetSideServerObject with Container {
|
||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private val inventory = GridInventory(30, 20)
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
def Faction: PlanetSideEmpire.Value = faction
|
||||
|
||||
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
|
||||
faction = fact
|
||||
Faction
|
||||
}
|
||||
|
||||
def Inventory : GridInventory = inventory
|
||||
def Inventory: GridInventory = inventory
|
||||
|
||||
def VisibleSlots : Set[Int] = Set.empty[Int]
|
||||
def VisibleSlots: Set[Int] = Set.empty[Int]
|
||||
|
||||
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container
|
||||
def Definition: EquipmentDefinition = GlobalDefinitions.locker_container
|
||||
}
|
||||
|
||||
object LockerContainer {
|
||||
def apply() : LockerContainer = {
|
||||
def apply(): LockerContainer = {
|
||||
new LockerContainer()
|
||||
}
|
||||
}
|
||||
|
||||
class LockerEquipment(locker : LockerContainer) extends Equipment
|
||||
with Container {
|
||||
class LockerEquipment(locker: LockerContainer) extends Equipment with Container {
|
||||
private val obj = locker
|
||||
|
||||
override def GUID : PlanetSideGUID = obj.GUID
|
||||
override def GUID: PlanetSideGUID = obj.GUID
|
||||
|
||||
override def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = obj.GUID_=(guid)
|
||||
override def GUID_=(guid: PlanetSideGUID): PlanetSideGUID = obj.GUID_=(guid)
|
||||
|
||||
override def HasGUID : Boolean = obj.HasGUID
|
||||
override def HasGUID: Boolean = obj.HasGUID
|
||||
|
||||
override def Invalidate() : Unit = obj.Invalidate()
|
||||
override def Invalidate(): Unit = obj.Invalidate()
|
||||
|
||||
override def Faction : PlanetSideEmpire.Value = obj.Faction
|
||||
override def Faction: PlanetSideEmpire.Value = obj.Faction
|
||||
|
||||
def Inventory : GridInventory = obj.Inventory
|
||||
def Inventory: GridInventory = obj.Inventory
|
||||
|
||||
def VisibleSlots : Set[Int] = Set.empty[Int]
|
||||
def VisibleSlots: Set[Int] = Set.empty[Int]
|
||||
|
||||
def Definition : EquipmentDefinition = obj.Definition
|
||||
def Definition: EquipmentDefinition = obj.Definition
|
||||
}
|
||||
|
||||
class LockerContainerControl(locker : LockerContainer, toChannel : String) extends Actor
|
||||
with ContainableBehavior {
|
||||
class LockerContainerControl(locker: LockerContainer, toChannel: String) extends Actor with ContainableBehavior {
|
||||
def ContainerObject = locker
|
||||
|
||||
def receive : Receive = containerBehavior
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def receive: Receive =
|
||||
containerBehavior
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
def MessageDeferredCallback(msg : Any) : Unit = {
|
||||
def MessageDeferredCallback(msg: Any): Unit = {
|
||||
msg match {
|
||||
case Containable.MoveItem(_, item, _) =>
|
||||
//momentarily put item back where it was originally
|
||||
|
|
@ -91,13 +89,13 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
|
|||
}
|
||||
}
|
||||
|
||||
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = {
|
||||
def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
|
||||
val zone = locker.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
|
||||
}
|
||||
|
||||
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = {
|
||||
val zone = locker.Zone
|
||||
def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
|
||||
val zone = locker.Zone
|
||||
val definition = item.Definition
|
||||
item.Faction = PlanetSideEmpire.NEUTRAL
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
|
|
@ -114,8 +112,14 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
|
|||
)
|
||||
}
|
||||
|
||||
def SwapItemCallback(item : Equipment) : Unit = {
|
||||
def SwapItemCallback(item: Equipment): Unit = {
|
||||
val zone = locker.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.SendResponse(Service.defaultPlayerGUID, ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f)))
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
toChannel,
|
||||
AvatarAction.SendResponse(
|
||||
Service.defaultPlayerGUID,
|
||||
ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,93 +4,93 @@ package net.psforever.objects
|
|||
object ObjectType extends Enumeration {
|
||||
type Value = String
|
||||
|
||||
val AmbientSoundSource = "ambient_sound_source"
|
||||
val Ammunition = "ammunition"
|
||||
val AnimatedBarrier = "animated_barrier"
|
||||
val Applicator = "applicator"
|
||||
val Armor = "armor"
|
||||
val ArmorSiphon = "armor_siphon"
|
||||
val AwardStatistic = "award_statistic"
|
||||
val Avatar = "avatar"
|
||||
val AvatarBot = "avatar_bot"
|
||||
val Ball = "ball"
|
||||
val Bank = "bank"
|
||||
val Barrier = "barrier"
|
||||
val BfrTerminal = "bfr_terminal"
|
||||
val Billboard = "billboard"
|
||||
val Boomer = "boomer"
|
||||
val BoomerTrigger = "boomer_trigger"
|
||||
val Building = "building"
|
||||
val CaptureFlag = "capture_flag"
|
||||
val CaptureFlagSocket = "capture_flag_socket"
|
||||
val CaptureTerminal = "capture_terminal"
|
||||
val CertTerminal = "cert_terminal"
|
||||
val ChainLashDamager = "chain_lash_damager"
|
||||
val Dispenser = "dispenser"
|
||||
val Door = "door"
|
||||
val EmpBlast = "emp_blast"
|
||||
val FrameVehicle = "framevehicle"
|
||||
val Flag = "flag"
|
||||
val FlightVehicle = "flightvehicle"
|
||||
val ForceDome = "forcedome"
|
||||
val ForceDomeGenerator = "forcedomegenerator"
|
||||
val Game = "game"
|
||||
val Generic = "generic"
|
||||
val GenericTeleportion = "generic_teleportation"
|
||||
val GeneratorTerminal = "generator_terminal"
|
||||
val GsGenbase = "GS_genbase"
|
||||
val HandGrenade = "hand_grenade"
|
||||
val HeMine = "he_mine"
|
||||
val HeavyWeapon = "heavy_weapon"
|
||||
val HoverVehicle = "hovervehicle"
|
||||
val Implant = "implant"
|
||||
val AmbientSoundSource = "ambient_sound_source"
|
||||
val Ammunition = "ammunition"
|
||||
val AnimatedBarrier = "animated_barrier"
|
||||
val Applicator = "applicator"
|
||||
val Armor = "armor"
|
||||
val ArmorSiphon = "armor_siphon"
|
||||
val AwardStatistic = "award_statistic"
|
||||
val Avatar = "avatar"
|
||||
val AvatarBot = "avatar_bot"
|
||||
val Ball = "ball"
|
||||
val Bank = "bank"
|
||||
val Barrier = "barrier"
|
||||
val BfrTerminal = "bfr_terminal"
|
||||
val Billboard = "billboard"
|
||||
val Boomer = "boomer"
|
||||
val BoomerTrigger = "boomer_trigger"
|
||||
val Building = "building"
|
||||
val CaptureFlag = "capture_flag"
|
||||
val CaptureFlagSocket = "capture_flag_socket"
|
||||
val CaptureTerminal = "capture_terminal"
|
||||
val CertTerminal = "cert_terminal"
|
||||
val ChainLashDamager = "chain_lash_damager"
|
||||
val Dispenser = "dispenser"
|
||||
val Door = "door"
|
||||
val EmpBlast = "emp_blast"
|
||||
val FrameVehicle = "framevehicle"
|
||||
val Flag = "flag"
|
||||
val FlightVehicle = "flightvehicle"
|
||||
val ForceDome = "forcedome"
|
||||
val ForceDomeGenerator = "forcedomegenerator"
|
||||
val Game = "game"
|
||||
val Generic = "generic"
|
||||
val GenericTeleportion = "generic_teleportation"
|
||||
val GeneratorTerminal = "generator_terminal"
|
||||
val GsGenbase = "GS_genbase"
|
||||
val HandGrenade = "hand_grenade"
|
||||
val HeMine = "he_mine"
|
||||
val HeavyWeapon = "heavy_weapon"
|
||||
val HoverVehicle = "hovervehicle"
|
||||
val Implant = "implant"
|
||||
val ImplantInterfaceTerminal = "implant_terminal_interface"
|
||||
val Lazer = "lazer"
|
||||
val Locker = "locker"
|
||||
val LockerContainer = "locker_container"
|
||||
val LockExternal = "lock_external"
|
||||
val LockSmall = "lock_small"
|
||||
val MainTerminal = "main_terminal"
|
||||
val Map = "map"
|
||||
val MedicalTerminal = "medical_terminal"
|
||||
val Medkit = "medkit"
|
||||
val Monolith = "monolith"
|
||||
val MonolithUnit = "monolith_unit"
|
||||
val MotionAlarmSensorDest = "motion_alarm_sensor_dest"
|
||||
val NanoDispenser = "nano_dispenser"
|
||||
val NtuSipon = "ntu_siphon"
|
||||
val OrbitalShuttlePad = "orbital_shuttle_pad"
|
||||
val OrbitalStrike = "orbital_strike"
|
||||
val OrderTerminal = "order_terminal"
|
||||
val PainTerminal = "pain_terminal"
|
||||
val Projectile = "projectile"
|
||||
val RadiationCloud = "radiation_cloud"
|
||||
val RearmTerminal = "rearm_terminal"
|
||||
val RechargeTerminal = "recharge_terminal"
|
||||
val Rek = "rek"
|
||||
val RepairTerminal = "repair_terminal"
|
||||
val ResourceSilo = "resource_silo"
|
||||
val RespawnTube = "respawn_tube"
|
||||
val SensorShield = "sensor_shield"
|
||||
val ShieldGenerator = "shield_generator"
|
||||
val Shifter = "shifter"
|
||||
val SkyDome = "skydome"
|
||||
val SpawnPlayer = "spawn_player"
|
||||
val SpawnPoint = "spawn_point"
|
||||
val SpawnTerminal = "spawn_terminal"
|
||||
val TeleportPad = "teleport_pad"
|
||||
val Terminal = "terminal"
|
||||
val TradeContainer = "trade_container"
|
||||
val UplinkDevice = "uplink_device"
|
||||
val VanuCradleClass = "vanu_cradle_class"
|
||||
val VanuModuleClass = "vanu_module_class"
|
||||
val VanuModuleFactory = "vanu_module_factory"
|
||||
val VanuReceptacleClass = "vanu_receptacle_class"
|
||||
val Vehicle = "vehicle"
|
||||
val VehicleCreationPad = "vehicle_creation_pad"
|
||||
val VehicleLandingPad = "vehicle_landing_pad"
|
||||
val VehicleTerminal = "vehicle_terminal"
|
||||
val Warpgate = "waprgate"
|
||||
val WarpZone = "warp_zone"
|
||||
val Weapon = "weapon"
|
||||
val Lazer = "lazer"
|
||||
val Locker = "locker"
|
||||
val LockerContainer = "locker_container"
|
||||
val LockExternal = "lock_external"
|
||||
val LockSmall = "lock_small"
|
||||
val MainTerminal = "main_terminal"
|
||||
val Map = "map"
|
||||
val MedicalTerminal = "medical_terminal"
|
||||
val Medkit = "medkit"
|
||||
val Monolith = "monolith"
|
||||
val MonolithUnit = "monolith_unit"
|
||||
val MotionAlarmSensorDest = "motion_alarm_sensor_dest"
|
||||
val NanoDispenser = "nano_dispenser"
|
||||
val NtuSipon = "ntu_siphon"
|
||||
val OrbitalShuttlePad = "orbital_shuttle_pad"
|
||||
val OrbitalStrike = "orbital_strike"
|
||||
val OrderTerminal = "order_terminal"
|
||||
val PainTerminal = "pain_terminal"
|
||||
val Projectile = "projectile"
|
||||
val RadiationCloud = "radiation_cloud"
|
||||
val RearmTerminal = "rearm_terminal"
|
||||
val RechargeTerminal = "recharge_terminal"
|
||||
val Rek = "rek"
|
||||
val RepairTerminal = "repair_terminal"
|
||||
val ResourceSilo = "resource_silo"
|
||||
val RespawnTube = "respawn_tube"
|
||||
val SensorShield = "sensor_shield"
|
||||
val ShieldGenerator = "shield_generator"
|
||||
val Shifter = "shifter"
|
||||
val SkyDome = "skydome"
|
||||
val SpawnPlayer = "spawn_player"
|
||||
val SpawnPoint = "spawn_point"
|
||||
val SpawnTerminal = "spawn_terminal"
|
||||
val TeleportPad = "teleport_pad"
|
||||
val Terminal = "terminal"
|
||||
val TradeContainer = "trade_container"
|
||||
val UplinkDevice = "uplink_device"
|
||||
val VanuCradleClass = "vanu_cradle_class"
|
||||
val VanuModuleClass = "vanu_module_class"
|
||||
val VanuModuleFactory = "vanu_module_factory"
|
||||
val VanuReceptacleClass = "vanu_receptacle_class"
|
||||
val Vehicle = "vehicle"
|
||||
val VehicleCreationPad = "vehicle_creation_pad"
|
||||
val VehicleLandingPad = "vehicle_landing_pad"
|
||||
val VehicleTerminal = "vehicle_terminal"
|
||||
val Warpgate = "waprgate"
|
||||
val WarpZone = "warp_zone"
|
||||
val Weapon = "weapon"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.equipment.{EquipmentSize, EquipmentSlot}
|
|||
* Unlike conventional `EquipmentSlot` space, this size of allowable `Equipment` is fixed.
|
||||
* @param size the permanent size of the `Equipment` allowed in this slot
|
||||
*/
|
||||
class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot {
|
||||
class OffhandEquipmentSlot(size: EquipmentSize.Value) extends EquipmentSlot {
|
||||
super.Size_=(size)
|
||||
|
||||
/**
|
||||
|
|
@ -16,10 +16,11 @@ class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot {
|
|||
* @param assignSize the changed in capacity for this slot
|
||||
* @return the capacity for this slot
|
||||
*/
|
||||
override def Size_=(assignSize : EquipmentSize.Value) : EquipmentSize.Value = Size
|
||||
override def Size_=(assignSize: EquipmentSize.Value): EquipmentSize.Value = Size
|
||||
}
|
||||
|
||||
object OffhandEquipmentSlot {
|
||||
|
||||
/**
|
||||
* An `EquipmentSlot` that can not be manipulated because its size is `Blocked` permanently.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ package net.psforever.objects
|
|||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
trait OwnableByPlayer {
|
||||
private var owner : Option[PlanetSideGUID] = None
|
||||
private var ownerName : Option[String] = None
|
||||
private var owner: Option[PlanetSideGUID] = None
|
||||
private var ownerName: Option[String] = None
|
||||
|
||||
def Owner : Option[PlanetSideGUID] = owner
|
||||
def Owner: Option[PlanetSideGUID] = owner
|
||||
|
||||
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner))
|
||||
def Owner_=(owner: PlanetSideGUID): Option[PlanetSideGUID] = Owner_=(Some(owner))
|
||||
|
||||
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
|
||||
def Owner_=(owner: Player): Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
|
||||
|
||||
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def Owner_=(owner: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
this.owner = owner
|
||||
|
|
@ -23,13 +23,13 @@ trait OwnableByPlayer {
|
|||
Owner
|
||||
}
|
||||
|
||||
def OwnerName : Option[String] = ownerName
|
||||
def OwnerName: Option[String] = ownerName
|
||||
|
||||
def OwnerName_=(owner : String) : Option[String] = OwnerName_=(Some(owner))
|
||||
def OwnerName_=(owner: String): Option[String] = OwnerName_=(Some(owner))
|
||||
|
||||
def OwnerName_=(owner : Player) : Option[String] = OwnerName_=(Some(owner.Name))
|
||||
def OwnerName_=(owner: Player): Option[String] = OwnerName_=(Some(owner.Name))
|
||||
|
||||
def OwnerName_=(owner : Option[String]) : Option[String] = {
|
||||
def OwnerName_=(owner: Option[String]): Option[String] = {
|
||||
owner match {
|
||||
case Some(_) =>
|
||||
ownerName = owner
|
||||
|
|
@ -44,14 +44,14 @@ trait OwnableByPlayer {
|
|||
* @param player na
|
||||
* @return na
|
||||
*/
|
||||
def AssignOwnership(player : Player) : OwnableByPlayer = AssignOwnership(Some(player))
|
||||
def AssignOwnership(player: Player): OwnableByPlayer = AssignOwnership(Some(player))
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param playerOpt na
|
||||
* @return na
|
||||
*/
|
||||
def AssignOwnership(playerOpt : Option[Player]) : OwnableByPlayer = {
|
||||
def AssignOwnership(playerOpt: Option[Player]): OwnableByPlayer = {
|
||||
playerOpt match {
|
||||
case Some(player) =>
|
||||
Owner = player
|
||||
|
|
|
|||
|
|
@ -9,47 +9,48 @@ import net.psforever.types.Vector3
|
|||
* A basic class that indicates an entity that exists somewhere in the world and has a globally unique identifier.
|
||||
*/
|
||||
abstract class PlanetSideGameObject extends IdentifiableEntity with WorldEntity {
|
||||
private var entity : WorldEntity = new SimpleWorldEntity()
|
||||
private var destroyed : Boolean = false
|
||||
private var entity: WorldEntity = new SimpleWorldEntity()
|
||||
private var destroyed: Boolean = false
|
||||
|
||||
def Entity : WorldEntity = entity
|
||||
def Entity: WorldEntity = entity
|
||||
|
||||
def Entity_=(newEntity : WorldEntity) : Unit = {
|
||||
def Entity_=(newEntity: WorldEntity): Unit = {
|
||||
entity = newEntity
|
||||
}
|
||||
|
||||
def Position : Vector3 = Entity.Position
|
||||
def Position: Vector3 = Entity.Position
|
||||
|
||||
def Position_=(vec : Vector3) : Vector3 = {
|
||||
def Position_=(vec: Vector3): Vector3 = {
|
||||
Entity.Position = vec
|
||||
}
|
||||
|
||||
def Orientation : Vector3 = Entity.Orientation
|
||||
def Orientation: Vector3 = Entity.Orientation
|
||||
|
||||
def Orientation_=(vec : Vector3) : Vector3 = {
|
||||
def Orientation_=(vec: Vector3): Vector3 = {
|
||||
Entity.Orientation = vec
|
||||
}
|
||||
|
||||
def Velocity : Option[Vector3] = Entity.Velocity
|
||||
def Velocity: Option[Vector3] = Entity.Velocity
|
||||
|
||||
def Velocity_=(vec : Option[Vector3]) : Option[Vector3] = {
|
||||
def Velocity_=(vec: Option[Vector3]): Option[Vector3] = {
|
||||
Entity.Velocity = vec
|
||||
}
|
||||
|
||||
def Destroyed : Boolean = destroyed
|
||||
def Destroyed: Boolean = destroyed
|
||||
|
||||
def Destroyed_=(state : Boolean) : Boolean = {
|
||||
def Destroyed_=(state: Boolean): Boolean = {
|
||||
destroyed = state
|
||||
Destroyed
|
||||
}
|
||||
|
||||
def Definition : ObjectDefinition
|
||||
def Definition: ObjectDefinition
|
||||
}
|
||||
|
||||
object PlanetSideGameObject {
|
||||
def toString(obj : PlanetSideGameObject) : String = {
|
||||
val guid : String = if(obj.HasGUID) { obj.GUID.toString } else { "NOGUID" }
|
||||
def toString(obj: PlanetSideGameObject): String = {
|
||||
val guid: String = if (obj.HasGUID) { obj.GUID.toString }
|
||||
else { "NOGUID" }
|
||||
val P = obj.Position
|
||||
s"[$guid](x,y,z=${P.x%.3f},${P.y%.3f},${P.z%.3f})"
|
||||
s"[$guid](x,y,z=${P.x % .3f},${P.y % .3f},${P.z % .3f})"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,12 @@
|
|||
package net.psforever.objects
|
||||
|
||||
import net.psforever.objects.avatar.LoadoutManager
|
||||
import net.psforever.objects.definition.{AvatarDefinition, ExoSuitDefinition, ImplantDefinition, SpecialExoSuitDefinition}
|
||||
import net.psforever.objects.definition.{
|
||||
AvatarDefinition,
|
||||
ExoSuitDefinition,
|
||||
ImplantDefinition,
|
||||
SpecialExoSuitDefinition
|
||||
}
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
|
||||
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
|
|
@ -16,76 +21,79 @@ import net.psforever.types.{PlanetSideGUID, _}
|
|||
import scala.annotation.tailrec
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
class Player(private val core : Avatar) extends PlanetSideServerObject
|
||||
with FactionAffinity
|
||||
with Vitality
|
||||
with ResistanceProfile
|
||||
with Container
|
||||
with JammableUnit
|
||||
with ZoneAware {
|
||||
Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead
|
||||
class Player(private val core: Avatar)
|
||||
extends PlanetSideServerObject
|
||||
with FactionAffinity
|
||||
with Vitality
|
||||
with ResistanceProfile
|
||||
with Container
|
||||
with JammableUnit
|
||||
with ZoneAware {
|
||||
Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead
|
||||
Destroyed = true //see isAlive
|
||||
private var backpack : Boolean = false
|
||||
private var stamina : Int = 0
|
||||
private var armor : Int = 0
|
||||
private var backpack: Boolean = false
|
||||
private var stamina: Int = 0
|
||||
private var armor: Int = 0
|
||||
|
||||
private var capacitor : Float = 0f
|
||||
private var capacitorState : CapacitorStateType.Value = CapacitorStateType.Idle
|
||||
private var capacitorLastUsedMillis : Long = 0
|
||||
private var capacitorLastChargedMillis : Long = 0
|
||||
private var capacitor: Float = 0f
|
||||
private var capacitorState: CapacitorStateType.Value = CapacitorStateType.Idle
|
||||
private var capacitorLastUsedMillis: Long = 0
|
||||
private var capacitorLastChargedMillis: Long = 0
|
||||
|
||||
private var maxStamina : Int = 100 //does anything affect this?
|
||||
private var maxStamina: Int = 100 //does anything affect this?
|
||||
|
||||
private var exosuit : ExoSuitDefinition = GlobalDefinitions.Standard
|
||||
private val freeHand : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
|
||||
private val holsters : Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
|
||||
private val inventory : GridInventory = GridInventory()
|
||||
private var drawnSlot : Int = Player.HandsDownSlot
|
||||
private var lastDrawnSlot : Int = Player.HandsDownSlot
|
||||
private var backpackAccess : Option[PlanetSideGUID] = None
|
||||
private var exosuit: ExoSuitDefinition = GlobalDefinitions.Standard
|
||||
private val freeHand: EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
|
||||
private val holsters: Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
|
||||
private val inventory: GridInventory = GridInventory()
|
||||
private var drawnSlot: Int = Player.HandsDownSlot
|
||||
private var lastDrawnSlot: Int = Player.HandsDownSlot
|
||||
private var backpackAccess: Option[PlanetSideGUID] = None
|
||||
|
||||
private var facingYawUpper : Float = 0f
|
||||
private var crouching : Boolean = false
|
||||
private var jumping : Boolean = false
|
||||
private var cloaked : Boolean = false
|
||||
private var fatigued : Boolean = false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina
|
||||
private var afk : Boolean = false
|
||||
private var facingYawUpper: Float = 0f
|
||||
private var crouching: Boolean = false
|
||||
private var jumping: Boolean = false
|
||||
private var cloaked: Boolean = false
|
||||
private var fatigued: Boolean =
|
||||
false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina
|
||||
private var afk: Boolean = false
|
||||
|
||||
private var vehicleSeated : Option[PlanetSideGUID] = None
|
||||
private var vehicleSeated: Option[PlanetSideGUID] = None
|
||||
|
||||
Continent = "home2" //the zone id
|
||||
|
||||
var spectator : Boolean = false
|
||||
var silenced : Boolean = false
|
||||
var death_by : Int = 0
|
||||
var lastSeenStreamMessage : Array[Long] = Array.fill[Long](65535)(0L)
|
||||
var lastShotSeq_time : Int = -1
|
||||
var spectator: Boolean = false
|
||||
var silenced: Boolean = false
|
||||
var death_by: Int = 0
|
||||
var lastSeenStreamMessage: Array[Long] = Array.fill[Long](65535)(0L)
|
||||
var lastShotSeq_time: Int = -1
|
||||
|
||||
/** From PlanetsideAttributeMessage */
|
||||
var PlanetsideAttribute : Array[Long] = Array.ofDim(120)
|
||||
var skipStaminaRegenForTurns : Int = 0
|
||||
var PlanetsideAttribute: Array[Long] = Array.ofDim(120)
|
||||
var skipStaminaRegenForTurns: Int = 0
|
||||
|
||||
Player.SuitSetup(this, exosuit)
|
||||
|
||||
def CharId : Long = core.CharId
|
||||
def CharId: Long = core.CharId
|
||||
|
||||
def Name : String = core.name
|
||||
def Name: String = core.name
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = core.faction
|
||||
def Faction: PlanetSideEmpire.Value = core.faction
|
||||
|
||||
def Sex : CharacterGender.Value = core.sex
|
||||
def Sex: CharacterGender.Value = core.sex
|
||||
|
||||
def Head : Int = core.head
|
||||
def Head: Int = core.head
|
||||
|
||||
def Voice : CharacterVoice.Value = core.voice
|
||||
def Voice: CharacterVoice.Value = core.voice
|
||||
|
||||
def LFS : Boolean = core.LFS
|
||||
def LFS: Boolean = core.LFS
|
||||
|
||||
def isAlive : Boolean = !Destroyed
|
||||
def isAlive: Boolean = !Destroyed
|
||||
|
||||
def isBackpack : Boolean = backpack
|
||||
def isBackpack: Boolean = backpack
|
||||
|
||||
def Spawn : Boolean = {
|
||||
if(!isAlive && !isBackpack) {
|
||||
def Spawn: Boolean = {
|
||||
if (!isAlive && !isBackpack) {
|
||||
Destroyed = false
|
||||
Health = Definition.DefaultHealth
|
||||
Stamina = MaxStamina
|
||||
|
|
@ -96,66 +104,64 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
isAlive
|
||||
}
|
||||
|
||||
def Die : Boolean = {
|
||||
def Die: Boolean = {
|
||||
Destroyed = true
|
||||
Health = 0
|
||||
Stamina = 0
|
||||
false
|
||||
}
|
||||
|
||||
def Revive : Boolean = {
|
||||
def Revive: Boolean = {
|
||||
Destroyed = false
|
||||
Health = Definition.DefaultHealth
|
||||
true
|
||||
}
|
||||
|
||||
def Release : Boolean = {
|
||||
if(!isAlive) {
|
||||
def Release: Boolean = {
|
||||
if (!isAlive) {
|
||||
backpack = true
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def Stamina : Int = stamina
|
||||
def Stamina: Int = stamina
|
||||
|
||||
def Stamina_=(assignStamina : Int) : Int = {
|
||||
stamina = if(isAlive) { math.min(math.max(0, assignStamina), MaxStamina) } else { 0 }
|
||||
def Stamina_=(assignStamina: Int): Int = {
|
||||
stamina = if (isAlive) { math.min(math.max(0, assignStamina), MaxStamina) }
|
||||
else { 0 }
|
||||
Stamina
|
||||
}
|
||||
|
||||
def MaxStamina : Int = maxStamina
|
||||
def MaxStamina: Int = maxStamina
|
||||
|
||||
def MaxStamina_=(max : Int) : Int = {
|
||||
def MaxStamina_=(max: Int): Int = {
|
||||
maxStamina = math.min(math.max(0, max), 65535)
|
||||
MaxStamina
|
||||
}
|
||||
|
||||
def Armor : Int = armor
|
||||
def Armor: Int = armor
|
||||
|
||||
def Armor_=(assignArmor : Int) : Int = {
|
||||
def Armor_=(assignArmor: Int): Int = {
|
||||
armor = math.min(math.max(0, assignArmor), MaxArmor)
|
||||
Armor
|
||||
}
|
||||
|
||||
def MaxArmor : Int = exosuit.MaxArmor
|
||||
def MaxArmor: Int = exosuit.MaxArmor
|
||||
|
||||
def Capacitor : Float = capacitor
|
||||
def Capacitor: Float = capacitor
|
||||
|
||||
def Capacitor_=(value : Float) : Float = {
|
||||
def Capacitor_=(value: Float): Float = {
|
||||
val newValue = math.min(math.max(0, value), ExoSuitDef.MaxCapacitor.toFloat)
|
||||
|
||||
if(newValue < capacitor) {
|
||||
if (newValue < capacitor) {
|
||||
capacitorLastUsedMillis = System.currentTimeMillis()
|
||||
capacitorLastChargedMillis = 0
|
||||
}
|
||||
else if(newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
|
||||
} else if (newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
|
||||
capacitorLastChargedMillis = System.currentTimeMillis()
|
||||
capacitorLastUsedMillis = 0
|
||||
}
|
||||
else if(newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
|
||||
} else if (newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
|
||||
capacitorLastChargedMillis = 0
|
||||
capacitorLastUsedMillis = 0
|
||||
capacitorState = CapacitorStateType.Idle
|
||||
|
|
@ -165,55 +171,51 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
capacitor
|
||||
}
|
||||
|
||||
def CapacitorState : CapacitorStateType.Value = capacitorState
|
||||
def CapacitorState_=(value : CapacitorStateType.Value) : CapacitorStateType.Value = {
|
||||
def CapacitorState: CapacitorStateType.Value = capacitorState
|
||||
def CapacitorState_=(value: CapacitorStateType.Value): CapacitorStateType.Value = {
|
||||
value match {
|
||||
case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis()
|
||||
case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis()
|
||||
case CapacitorStateType.Discharging => capacitorLastUsedMillis = System.currentTimeMillis()
|
||||
case _ => ;
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
capacitorState = value
|
||||
capacitorState
|
||||
}
|
||||
|
||||
def CapacitorLastUsedMillis = capacitorLastUsedMillis
|
||||
def CapacitorLastUsedMillis = capacitorLastUsedMillis
|
||||
def CapacitorLastChargedMillis = capacitorLastChargedMillis
|
||||
|
||||
def VisibleSlots : Set[Int] = if(exosuit.SuitType == ExoSuitType.MAX) {
|
||||
Set(0)
|
||||
}
|
||||
else {
|
||||
(0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet
|
||||
}
|
||||
def VisibleSlots: Set[Int] =
|
||||
if (exosuit.SuitType == ExoSuitType.MAX) {
|
||||
Set(0)
|
||||
} else {
|
||||
(0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet
|
||||
}
|
||||
|
||||
override def Slot(slot : Int) : EquipmentSlot = {
|
||||
if(inventory.Offset <= slot && slot <= inventory.LastIndex) {
|
||||
override def Slot(slot: Int): EquipmentSlot = {
|
||||
if (inventory.Offset <= slot && slot <= inventory.LastIndex) {
|
||||
inventory.Slot(slot)
|
||||
}
|
||||
else if(slot > -1 && slot < 5) {
|
||||
} else if (slot > -1 && slot < 5) {
|
||||
holsters(slot)
|
||||
}
|
||||
else if(slot == 5) {
|
||||
} else if (slot == 5) {
|
||||
core.FifthSlot
|
||||
}
|
||||
else if(slot == Player.FreeHandSlot) {
|
||||
} else if (slot == Player.FreeHandSlot) {
|
||||
freeHand
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
OffhandEquipmentSlot.BlockedSlot
|
||||
}
|
||||
}
|
||||
|
||||
def Holsters() : Array[EquipmentSlot] = holsters
|
||||
def Holsters(): Array[EquipmentSlot] = holsters
|
||||
|
||||
def Inventory : GridInventory = inventory
|
||||
def Inventory: GridInventory = inventory
|
||||
|
||||
def Locker : LockerContainer = core.Locker
|
||||
def Locker: LockerContainer = core.Locker
|
||||
|
||||
def FifthSlot : EquipmentSlot = core.FifthSlot
|
||||
def FifthSlot: EquipmentSlot = core.FifthSlot
|
||||
|
||||
override def Fit(obj : Equipment) : Option[Int] = {
|
||||
override def Fit(obj: Equipment): Option[Int] = {
|
||||
recursiveHolsterFit(holsters.iterator, obj.Size) match {
|
||||
case Some(index) =>
|
||||
Some(index)
|
||||
|
|
@ -222,21 +224,24 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
case Some(index) =>
|
||||
Some(index)
|
||||
case None =>
|
||||
if(freeHand.Equipment.isDefined) { None } else { Some(Player.FreeHandSlot) }
|
||||
if (freeHand.Equipment.isDefined) { None }
|
||||
else { Some(Player.FreeHandSlot) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@tailrec private def recursiveHolsterFit(iter : Iterator[EquipmentSlot], objSize : EquipmentSize.Value, index : Int = 0) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursiveHolsterFit(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
objSize: EquipmentSize.Value,
|
||||
index: Int = 0
|
||||
): Option[Int] = {
|
||||
if (!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val slot = iter.next
|
||||
if(slot.Equipment.isEmpty && slot.Size.equals(objSize)) {
|
||||
if (slot.Equipment.isEmpty && slot.Size.equals(objSize)) {
|
||||
Some(index)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
recursiveHolsterFit(iter, objSize, index + 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -244,73 +249,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
|
||||
def FreeHand = freeHand
|
||||
|
||||
def FreeHand_=(item : Option[Equipment]) : Option[Equipment] = {
|
||||
if(freeHand.Equipment.isEmpty || item.isEmpty) {
|
||||
def FreeHand_=(item: Option[Equipment]): Option[Equipment] = {
|
||||
if (freeHand.Equipment.isEmpty || item.isEmpty) {
|
||||
freeHand.Equipment = item
|
||||
}
|
||||
FreeHand.Equipment
|
||||
}
|
||||
|
||||
override def Find(guid : PlanetSideGUID) : Option[Int] = {
|
||||
override def Find(guid: PlanetSideGUID): Option[Int] = {
|
||||
findInHolsters(holsters.iterator, guid)
|
||||
.orElse(inventory.Find(guid)) match {
|
||||
case Some(index) =>
|
||||
Some(index)
|
||||
case None =>
|
||||
if(freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) {
|
||||
if (freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) {
|
||||
Some(Player.FreeHandSlot)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@tailrec private def findInHolsters(iter : Iterator[EquipmentSlot], guid : PlanetSideGUID, index : Int = 0) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def findInHolsters(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
guid: PlanetSideGUID,
|
||||
index: Int = 0
|
||||
): Option[Int] = {
|
||||
if (!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val slot = iter.next
|
||||
if(slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) {
|
||||
if (slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) {
|
||||
Some(index)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
findInHolsters(iter, guid, index + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = {
|
||||
if(-1 < dest && dest < 5) {
|
||||
override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
|
||||
if (-1 < dest && dest < 5) {
|
||||
holsters(dest).Equipment match {
|
||||
case Some(item) =>
|
||||
Success(List(InventoryItem(item, dest)))
|
||||
case None =>
|
||||
Success(List())
|
||||
}
|
||||
}
|
||||
else if(dest == Player.FreeHandSlot) {
|
||||
} else if (dest == Player.FreeHandSlot) {
|
||||
freeHand.Equipment match {
|
||||
case Some(item) =>
|
||||
Success(List(InventoryItem(item, dest)))
|
||||
case None =>
|
||||
Success(List())
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
super.Collisions(dest, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
def DrawnSlot : Int = drawnSlot
|
||||
def DrawnSlot: Int = drawnSlot
|
||||
|
||||
def DrawnSlot_=(slot : Int) : Int = {
|
||||
if(slot != drawnSlot) {
|
||||
if(slot == Player.HandsDownSlot) {
|
||||
def DrawnSlot_=(slot: Int): Int = {
|
||||
if (slot != drawnSlot) {
|
||||
if (slot == Player.HandsDownSlot) {
|
||||
drawnSlot = slot
|
||||
}
|
||||
else if(VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
|
||||
} else if (VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
|
||||
drawnSlot = slot
|
||||
lastDrawnSlot = slot
|
||||
}
|
||||
|
|
@ -318,12 +321,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
DrawnSlot
|
||||
}
|
||||
|
||||
def LastDrawnSlot : Int = lastDrawnSlot
|
||||
def LastDrawnSlot: Int = lastDrawnSlot
|
||||
|
||||
def ExoSuit : ExoSuitType.Value = exosuit.SuitType
|
||||
def ExoSuitDef : ExoSuitDefinition = exosuit
|
||||
def ExoSuit: ExoSuitType.Value = exosuit.SuitType
|
||||
def ExoSuitDef: ExoSuitDefinition = exosuit
|
||||
|
||||
def ExoSuit_=(suit : ExoSuitType.Value) : Unit = {
|
||||
def ExoSuit_=(suit: ExoSuitType.Value): Unit = {
|
||||
val eSuit = ExoSuitDefinition.Select(suit, Faction)
|
||||
exosuit = eSuit
|
||||
Player.SuitSetup(this, eSuit)
|
||||
|
|
@ -340,15 +343,15 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
|
||||
def RadiationShielding = exosuit.RadiationShielding
|
||||
|
||||
def EquipmentLoadouts : LoadoutManager = core.EquipmentLoadouts
|
||||
def EquipmentLoadouts: LoadoutManager = core.EquipmentLoadouts
|
||||
|
||||
def SquadLoadouts : LoadoutManager = core.SquadLoadouts
|
||||
def SquadLoadouts: LoadoutManager = core.SquadLoadouts
|
||||
|
||||
def BEP : Long = core.BEP
|
||||
def BEP: Long = core.BEP
|
||||
|
||||
def CEP : Long = core.CEP
|
||||
def CEP: Long = core.CEP
|
||||
|
||||
def Certifications : Set[CertificationType.Value] = core.Certifications.toSet
|
||||
def Certifications: Set[CertificationType.Value] = core.Certifications.toSet
|
||||
|
||||
/**
|
||||
* What kind of implant is installed into the given slot number?
|
||||
|
|
@ -356,71 +359,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
* @param slot the slot number
|
||||
* @return the tye of implant
|
||||
*/
|
||||
def Implant(slot : Int) : ImplantType.Value = core.Implant(slot)
|
||||
def Implant(slot: Int): ImplantType.Value = core.Implant(slot)
|
||||
|
||||
def ImplantSlot(slot: Int) : ImplantSlot = core.Implants(slot)
|
||||
def ImplantSlot(slot: Int): ImplantSlot = core.Implants(slot)
|
||||
|
||||
/**
|
||||
* A read-only `Array` of tuples representing important information about all unlocked implant slots.
|
||||
* @return a maximum of three implant types, initialization times, and active flags
|
||||
*/
|
||||
def Implants : Array[(ImplantType.Value, Long, Boolean)] = {
|
||||
core.Implants.takeWhile(_.Unlocked).map( implant => { (implant.Implant, implant.MaxTimer, implant.Active) })
|
||||
def Implants: Array[(ImplantType.Value, Long, Boolean)] = {
|
||||
core.Implants.takeWhile(_.Unlocked).map(implant => { (implant.Implant, implant.MaxTimer, implant.Active) })
|
||||
}
|
||||
|
||||
def InstallImplant(implant : ImplantDefinition) : Option[Int] = core.InstallImplant(implant)
|
||||
def InstallImplant(implant: ImplantDefinition): Option[Int] = core.InstallImplant(implant)
|
||||
|
||||
def UninstallImplant(implant : ImplantType.Value) : Option[Int] = core.UninstallImplant(implant)
|
||||
def UninstallImplant(implant: ImplantType.Value): Option[Int] = core.UninstallImplant(implant)
|
||||
|
||||
def ResetAllImplants() : Unit = core.ResetAllImplants()
|
||||
def ResetAllImplants(): Unit = core.ResetAllImplants()
|
||||
|
||||
def FacingYawUpper : Float = facingYawUpper
|
||||
def FacingYawUpper: Float = facingYawUpper
|
||||
|
||||
def FacingYawUpper_=(facing : Float) : Float = {
|
||||
def FacingYawUpper_=(facing: Float): Float = {
|
||||
facingYawUpper = facing
|
||||
FacingYawUpper
|
||||
}
|
||||
|
||||
def Crouching : Boolean = crouching
|
||||
def Crouching: Boolean = crouching
|
||||
|
||||
def Crouching_=(crouched : Boolean) : Boolean = {
|
||||
def Crouching_=(crouched: Boolean): Boolean = {
|
||||
crouching = crouched
|
||||
Crouching
|
||||
}
|
||||
|
||||
def Jumping : Boolean = jumping
|
||||
def Jumping: Boolean = jumping
|
||||
|
||||
def Jumping_=(jumped : Boolean) : Boolean = {
|
||||
def Jumping_=(jumped: Boolean): Boolean = {
|
||||
jumping = jumped
|
||||
Jumping
|
||||
}
|
||||
|
||||
def Cloaked : Boolean = cloaked
|
||||
def Cloaked: Boolean = cloaked
|
||||
|
||||
def Cloaked_=(isCloaked : Boolean) : Boolean = {
|
||||
def Cloaked_=(isCloaked: Boolean): Boolean = {
|
||||
cloaked = isCloaked
|
||||
Cloaked
|
||||
}
|
||||
|
||||
def Fatigued : Boolean = fatigued
|
||||
def Fatigued: Boolean = fatigued
|
||||
|
||||
def Fatigued_=(isFatigued : Boolean) : Boolean = {
|
||||
def Fatigued_=(isFatigued: Boolean): Boolean = {
|
||||
fatigued = isFatigued
|
||||
Fatigued
|
||||
}
|
||||
|
||||
def AwayFromKeyboard : Boolean = afk
|
||||
def AwayFromKeyboard: Boolean = afk
|
||||
|
||||
def AwayFromKeyboard_=(away : Boolean) : Boolean = {
|
||||
def AwayFromKeyboard_=(away: Boolean): Boolean = {
|
||||
afk = away
|
||||
AwayFromKeyboard
|
||||
}
|
||||
|
||||
def PersonalStyleFeatures : Option[Cosmetics] = core.PersonalStyleFeatures
|
||||
def PersonalStyleFeatures: Option[Cosmetics] = core.PersonalStyleFeatures
|
||||
|
||||
def AddToPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
def AddToPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
val original = core.PersonalStyleFeatures
|
||||
if(DetailedCharacterData.isBR24(core.BEP)) {
|
||||
if (DetailedCharacterData.isBR24(core.BEP)) {
|
||||
core.PersonalStyleFeatures = original match {
|
||||
case Some(cosmetic) =>
|
||||
cosmetic + value
|
||||
|
|
@ -428,51 +431,47 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
Cosmetics(value)
|
||||
}
|
||||
(original, core.PersonalStyleFeatures)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
|
||||
def RemoveFromPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
def RemoveFromPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
val original = core.PersonalStyleFeatures
|
||||
original match {
|
||||
case Some(cosmetics) =>
|
||||
(original, core.PersonalStyleFeatures = cosmetics - value)
|
||||
case None =>
|
||||
(None, None)
|
||||
}
|
||||
original match {
|
||||
case Some(cosmetics) =>
|
||||
(original, core.PersonalStyleFeatures = cosmetics - value)
|
||||
case None =>
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
|
||||
private def BasicFeatureToggle(feature : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = core.PersonalStyleFeatures match {
|
||||
case Some(c : Cosmetics) =>
|
||||
if(c.Styles.contains(feature)) {
|
||||
RemoveFromPersonalStyle(feature)
|
||||
}
|
||||
else {
|
||||
AddToPersonalStyle(feature)
|
||||
}
|
||||
case None =>
|
||||
AddToPersonalStyle(feature)
|
||||
}
|
||||
|
||||
def ToggleHelmet : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
|
||||
|
||||
def ToggleShades : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
|
||||
|
||||
def ToggleEarpiece : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
|
||||
|
||||
def ToggleHat : (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
private def BasicFeatureToggle(feature: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) =
|
||||
core.PersonalStyleFeatures match {
|
||||
case Some(c : Cosmetics) =>
|
||||
if(c.Styles.contains(PersonalStyle.BrimmedCap)) {
|
||||
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1,
|
||||
AddToPersonalStyle(PersonalStyle.Beret)._2)
|
||||
case Some(c: Cosmetics) =>
|
||||
if (c.Styles.contains(feature)) {
|
||||
RemoveFromPersonalStyle(feature)
|
||||
} else {
|
||||
AddToPersonalStyle(feature)
|
||||
}
|
||||
else if(c.Styles.contains(PersonalStyle.Beret)) {
|
||||
case None =>
|
||||
AddToPersonalStyle(feature)
|
||||
}
|
||||
|
||||
def ToggleHelmet: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
|
||||
|
||||
def ToggleShades: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
|
||||
|
||||
def ToggleEarpiece: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
|
||||
|
||||
def ToggleHat: (Option[Cosmetics], Option[Cosmetics]) = {
|
||||
core.PersonalStyleFeatures match {
|
||||
case Some(c: Cosmetics) =>
|
||||
if (c.Styles.contains(PersonalStyle.BrimmedCap)) {
|
||||
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1, AddToPersonalStyle(PersonalStyle.Beret)._2)
|
||||
} else if (c.Styles.contains(PersonalStyle.Beret)) {
|
||||
RemoveFromPersonalStyle(PersonalStyle.Beret)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AddToPersonalStyle(PersonalStyle.BrimmedCap)
|
||||
}
|
||||
case None =>
|
||||
|
|
@ -480,96 +479,99 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
}
|
||||
}
|
||||
|
||||
private var usingSpecial : SpecialExoSuitDefinition.Mode.Value=>SpecialExoSuitDefinition.Mode.Value = DefaultUsingSpecial
|
||||
private var usingSpecial: SpecialExoSuitDefinition.Mode.Value => SpecialExoSuitDefinition.Mode.Value =
|
||||
DefaultUsingSpecial
|
||||
|
||||
private var gettingSpecial : ()=>SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial
|
||||
private var gettingSpecial: () => SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial
|
||||
|
||||
private def ChangeSpecialAbility() : Unit = {
|
||||
if(ExoSuit == ExoSuitType.MAX) {
|
||||
private def ChangeSpecialAbility(): Unit = {
|
||||
if (ExoSuit == ExoSuitType.MAX) {
|
||||
gettingSpecial = MAXGettingSpecial
|
||||
usingSpecial = Faction match {
|
||||
case PlanetSideEmpire.TR => UsingAnchorsOrOverdrive
|
||||
case PlanetSideEmpire.NC => UsingShield
|
||||
case _ => DefaultUsingSpecial
|
||||
case _ => DefaultUsingSpecial
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
usingSpecial = DefaultUsingSpecial
|
||||
gettingSpecial = DefaultGettingSpecial
|
||||
}
|
||||
}
|
||||
|
||||
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() }
|
||||
def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() }
|
||||
|
||||
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = usingSpecial(state)
|
||||
def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
|
||||
usingSpecial(state)
|
||||
|
||||
private def DefaultUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
|
||||
private def DefaultUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
|
||||
SpecialExoSuitDefinition.Mode.Normal
|
||||
|
||||
private def UsingAnchorsOrOverdrive(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
|
||||
private def UsingAnchorsOrOverdrive(
|
||||
state: SpecialExoSuitDefinition.Mode.Value
|
||||
): SpecialExoSuitDefinition.Mode.Value = {
|
||||
import SpecialExoSuitDefinition.Mode._
|
||||
val curr = UsingSpecial
|
||||
val next = if(curr == Normal) {
|
||||
if(state == Anchored || state == Overdrive) {
|
||||
val next = if (curr == Normal) {
|
||||
if (state == Anchored || state == Overdrive) {
|
||||
state
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Normal
|
||||
}
|
||||
}
|
||||
else if(state == Normal) {
|
||||
} else if (state == Normal) {
|
||||
Normal
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
curr
|
||||
}
|
||||
MAXUsingSpecial(next)
|
||||
}
|
||||
|
||||
private def UsingShield(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
|
||||
private def UsingShield(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
|
||||
import SpecialExoSuitDefinition.Mode._
|
||||
val curr = UsingSpecial
|
||||
val next = if(curr == Normal) {
|
||||
if(state == Shielded) {
|
||||
val next = if (curr == Normal) {
|
||||
if (state == Shielded) {
|
||||
state
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Normal
|
||||
}
|
||||
}
|
||||
else if(state == Normal) {
|
||||
} else if (state == Normal) {
|
||||
Normal
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
curr
|
||||
}
|
||||
MAXUsingSpecial(next)
|
||||
}
|
||||
|
||||
private def DefaultGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
|
||||
private def DefaultGettingSpecial(): SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
|
||||
|
||||
private def MAXUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = exosuit match {
|
||||
case obj : SpecialExoSuitDefinition =>
|
||||
obj.UsingSpecial = state
|
||||
case _ =>
|
||||
SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
private def MAXUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
|
||||
exosuit match {
|
||||
case obj: SpecialExoSuitDefinition =>
|
||||
obj.UsingSpecial = state
|
||||
case _ =>
|
||||
SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
private def MAXGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = exosuit match {
|
||||
case obj : SpecialExoSuitDefinition =>
|
||||
obj.UsingSpecial
|
||||
case _ =>
|
||||
SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
private def MAXGettingSpecial(): SpecialExoSuitDefinition.Mode.Value =
|
||||
exosuit match {
|
||||
case obj: SpecialExoSuitDefinition =>
|
||||
obj.UsingSpecial
|
||||
case _ =>
|
||||
SpecialExoSuitDefinition.Mode.Normal
|
||||
}
|
||||
|
||||
def isAnchored : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored
|
||||
def isAnchored: Boolean =
|
||||
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored
|
||||
|
||||
def isOverdrived : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive
|
||||
def isOverdrived: Boolean =
|
||||
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive
|
||||
|
||||
def isShielded : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded
|
||||
def isShielded: Boolean =
|
||||
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded
|
||||
|
||||
def AccessingBackpack : Option[PlanetSideGUID] = backpackAccess
|
||||
def AccessingBackpack: Option[PlanetSideGUID] = backpackAccess
|
||||
|
||||
def AccessingBackpack_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = {
|
||||
def AccessingBackpack_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
|
||||
AccessingBackpack = Some(guid)
|
||||
}
|
||||
|
||||
|
|
@ -579,12 +581,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
* @param guid the player who wishes to access the backpack
|
||||
* @return the player who is currently allowed to access the backpack
|
||||
*/
|
||||
def AccessingBackpack_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def AccessingBackpack_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
guid match {
|
||||
case None =>
|
||||
backpackAccess = None
|
||||
case Some(player) =>
|
||||
if(isBackpack && backpackAccess.isEmpty) {
|
||||
if (isBackpack && backpackAccess.isEmpty) {
|
||||
backpackAccess = Some(player)
|
||||
}
|
||||
}
|
||||
|
|
@ -596,94 +598,96 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
|
|||
* @param player a player attempting to access this backpack
|
||||
* @return `true`, if the `player` is permitted access; `false`, otherwise
|
||||
*/
|
||||
def CanAccessBackpack(player : Player) : Boolean = {
|
||||
def CanAccessBackpack(player: Player): Boolean = {
|
||||
isBackpack && (backpackAccess.isEmpty || backpackAccess.contains(player.GUID))
|
||||
}
|
||||
|
||||
def FirstTimeEvents : List[String] = core.FirstTimeEvents
|
||||
def FirstTimeEvents: List[String] = core.FirstTimeEvents
|
||||
|
||||
def VehicleSeated : Option[PlanetSideGUID] = vehicleSeated
|
||||
def VehicleSeated: Option[PlanetSideGUID] = vehicleSeated
|
||||
|
||||
def VehicleSeated_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
|
||||
def VehicleSeated_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
|
||||
|
||||
def VehicleSeated_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def VehicleSeated_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
vehicleSeated = guid
|
||||
VehicleSeated
|
||||
}
|
||||
|
||||
def VehicleOwned : Option[PlanetSideGUID] = core.VehicleOwned
|
||||
def VehicleOwned: Option[PlanetSideGUID] = core.VehicleOwned
|
||||
|
||||
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid))
|
||||
def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid))
|
||||
|
||||
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = core.VehicleOwned_=(guid)
|
||||
def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = core.VehicleOwned_=(guid)
|
||||
|
||||
def GetLastUsedTime(code : Int) : Long = core.GetLastUsedTime(code)
|
||||
def GetLastUsedTime(code: Int): Long = core.GetLastUsedTime(code)
|
||||
|
||||
def GetLastUsedTime(code : ExoSuitType.Value) : Long = core.GetLastUsedTime(code)
|
||||
def GetLastUsedTime(code: ExoSuitType.Value): Long = core.GetLastUsedTime(code)
|
||||
|
||||
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = core.GetLastUsedTime(code, subtype)
|
||||
def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = core.GetLastUsedTime(code, subtype)
|
||||
|
||||
def SetLastUsedTime(code : Int, time : Long) : Unit = core.SetLastUsedTime(code, time)
|
||||
def SetLastUsedTime(code: Int, time: Long): Unit = core.SetLastUsedTime(code, time)
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value): Unit = core.SetLastUsedTime(code)
|
||||
def SetLastUsedTime(code: ExoSuitType.Value): Unit = core.SetLastUsedTime(code)
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = core.SetLastUsedTime(code, time)
|
||||
def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = core.SetLastUsedTime(code, time)
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int): Unit = core.SetLastUsedTime(code, subtype)
|
||||
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Unit = core.SetLastUsedTime(code, subtype)
|
||||
|
||||
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = core.SetLastUsedTime(code, subtype, time)
|
||||
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit =
|
||||
core.SetLastUsedTime(code, subtype, time)
|
||||
|
||||
def GetLastPurchaseTime(code : Int) : Long = core.GetLastPurchaseTime(code)
|
||||
def GetLastPurchaseTime(code: Int): Long = core.GetLastPurchaseTime(code)
|
||||
|
||||
def SetLastPurchaseTime(code : Int, time : Long) : Unit = core.SetLastPurchaseTime(code, time)
|
||||
def SetLastPurchaseTime(code: Int, time: Long): Unit = core.SetLastPurchaseTime(code, time)
|
||||
|
||||
def ObjectTypeNameReference(id : Long) : String = core.ObjectTypeNameReference(id)
|
||||
def ObjectTypeNameReference(id: Long): String = core.ObjectTypeNameReference(id)
|
||||
|
||||
def ObjectTypeNameReference(id : Long, name : String) : String = core.ObjectTypeNameReference(id, name)
|
||||
def ObjectTypeNameReference(id: Long, name: String): String = core.ObjectTypeNameReference(id, name)
|
||||
|
||||
def DamageModel = exosuit.asInstanceOf[DamageResistanceModel]
|
||||
|
||||
def Definition : AvatarDefinition = core.Definition
|
||||
def Definition: AvatarDefinition = core.Definition
|
||||
|
||||
def canEqual(other: Any): Boolean = other.isInstanceOf[Player]
|
||||
|
||||
override def equals(other : Any) : Boolean = other match {
|
||||
case that: Player =>
|
||||
(that canEqual this) &&
|
||||
core == that.core
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
override def equals(other: Any): Boolean =
|
||||
other match {
|
||||
case that: Player =>
|
||||
(that canEqual this) &&
|
||||
core == that.core
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
override def hashCode() : Int = {
|
||||
override def hashCode(): Int = {
|
||||
core.hashCode()
|
||||
}
|
||||
|
||||
override def toString : String = Player.toString(this)
|
||||
override def toString: String = Player.toString(this)
|
||||
}
|
||||
|
||||
object Player {
|
||||
final val LockerSlot : Int = 5
|
||||
final val FreeHandSlot : Int = 250
|
||||
final val HandsDownSlot : Int = 255
|
||||
final val LockerSlot: Int = 5
|
||||
final val FreeHandSlot: Int = 250
|
||||
final val HandsDownSlot: Int = 255
|
||||
|
||||
final case class Die()
|
||||
final case class ImplantActivation(slot : Int, status : Int)
|
||||
final case class ImplantInitializationStart(slot : Int)
|
||||
final case class UninitializeImplant(slot : Int)
|
||||
final case class ImplantInitializationComplete(slot : Int)
|
||||
final case class ImplantActivation(slot: Int, status: Int)
|
||||
final case class ImplantInitializationStart(slot: Int)
|
||||
final case class UninitializeImplant(slot: Int)
|
||||
final case class ImplantInitializationComplete(slot: Int)
|
||||
final case class StaminaRegen()
|
||||
final case class StaminaChanged(currentStamina : Option[Int] = None)
|
||||
final case class StaminaChanged(currentStamina: Option[Int] = None)
|
||||
|
||||
object StaminaChanged {
|
||||
def apply(amount : Int) : StaminaChanged = StaminaChanged(Some(amount))
|
||||
def apply(amount: Int): StaminaChanged = StaminaChanged(Some(amount))
|
||||
}
|
||||
|
||||
def apply(core : Avatar) : Player = {
|
||||
def apply(core: Avatar): Player = {
|
||||
new Player(core)
|
||||
}
|
||||
|
||||
private def SuitSetup(player : Player, eSuit : ExoSuitDefinition) : Unit = {
|
||||
private def SuitSetup(player: Player, eSuit: ExoSuitDefinition): Unit = {
|
||||
//inventory
|
||||
player.Inventory.Clear()
|
||||
player.Inventory.Resize(eSuit.InventoryScale.Width, eSuit.InventoryScale.Height)
|
||||
|
|
@ -692,34 +696,35 @@ object Player {
|
|||
(0 until 5).foreach(index => { player.Slot(index).Size = eSuit.Holster(index) })
|
||||
}
|
||||
|
||||
def Respawn(player : Player) : Player = {
|
||||
if(player.Release) {
|
||||
def Respawn(player: Player): Player = {
|
||||
if (player.Release) {
|
||||
val obj = new Player(player.core)
|
||||
obj.Continent = player.Continent
|
||||
obj
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
player
|
||||
}
|
||||
}
|
||||
|
||||
def GetHackLevel(player : Player): Int = {
|
||||
if(player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(CertificationType.ElectronicsExpert)) {
|
||||
def GetHackLevel(player: Player): Int = {
|
||||
if (
|
||||
player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(
|
||||
CertificationType.ElectronicsExpert
|
||||
)
|
||||
) {
|
||||
3
|
||||
}
|
||||
else if(player.Certifications.contains(CertificationType.AdvancedHacking)) {
|
||||
} else if (player.Certifications.contains(CertificationType.AdvancedHacking)) {
|
||||
2
|
||||
}
|
||||
else if (player.Certifications.contains(CertificationType.Hacking)) {
|
||||
} else if (player.Certifications.contains(CertificationType.Hacking)) {
|
||||
1
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
def toString(obj : Player) : String = {
|
||||
val guid = if(obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" } else { "" }
|
||||
def toString(obj: Player): String = {
|
||||
val guid = if (obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" }
|
||||
else { "" }
|
||||
s"${obj.core}$guid ${obj.Health}/${obj.MaxHealth} ${obj.Armor}/${obj.MaxArmor}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,17 +25,21 @@ object Players {
|
|||
* @return `true`, if the next cycle of progress should occur;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def RevivingTickAction(target : Player, user : Player, item : Tool)(progress : Float) : Boolean = {
|
||||
if(!target.isAlive && !target.isBackpack &&
|
||||
def RevivingTickAction(target: Player, user: Player, item: Tool)(progress: Float): Boolean = {
|
||||
if (
|
||||
!target.isAlive && !target.isBackpack &&
|
||||
user.isAlive && !user.isMoving &&
|
||||
user.Slot(user.DrawnSlot).Equipment.contains(item) && item.Magazine >= 25 &&
|
||||
Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance) {
|
||||
Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance
|
||||
) {
|
||||
val events = target.Zone.AvatarEvents
|
||||
val uname = user.Name
|
||||
events ! AvatarServiceMessage(uname, AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt)))
|
||||
val uname = user.Name
|
||||
events ! AvatarServiceMessage(
|
||||
uname,
|
||||
AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt))
|
||||
)
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -48,11 +52,17 @@ object Players {
|
|||
* @param medic the name of the player doing the reviving
|
||||
* @param item the tool being used to revive the target player
|
||||
*/
|
||||
def FinishRevivingPlayer(target : Player, medic : String, item : Tool)() : Unit = {
|
||||
def FinishRevivingPlayer(target: Player, medic: String, item: Tool)(): Unit = {
|
||||
val name = target.Name
|
||||
log.info(s"$medic had revived $name")
|
||||
val magazine = item.Discharge(Some(25))
|
||||
target.Zone.AvatarEvents ! AvatarServiceMessage(medic, AvatarAction.SendResponse(Service.defaultPlayerGUID, InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine)))
|
||||
target.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
medic,
|
||||
AvatarAction.SendResponse(
|
||||
Service.defaultPlayerGUID,
|
||||
InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine)
|
||||
)
|
||||
)
|
||||
target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID))
|
||||
}
|
||||
|
||||
|
|
@ -64,11 +74,14 @@ object Players {
|
|||
* @param list a persistent `List` of `Equipment` in the holster slots
|
||||
* @return a `List` of `Equipment` in the holster slots
|
||||
*/
|
||||
@tailrec def clearHolsters(iter : Iterator[EquipmentSlot], index : Int = 0, list : List[InventoryItem] = Nil) : List[InventoryItem] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec def clearHolsters(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
index: Int = 0,
|
||||
list: List[InventoryItem] = Nil
|
||||
): List[InventoryItem] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val slot = iter.next
|
||||
slot.Equipment match {
|
||||
case Some(equipment) =>
|
||||
|
|
@ -88,13 +101,12 @@ object Players {
|
|||
* @param list a `List` of all `Equipment` that is not yet assigned to a holster slot or an inventory slot
|
||||
* @return the `List` of all `Equipment` not yet assigned to a holster slot or an inventory slot
|
||||
*/
|
||||
@tailrec def fillEmptyHolsters(iter : Iterator[EquipmentSlot], list : List[InventoryItem]) : List[InventoryItem] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec def fillEmptyHolsters(iter: Iterator[EquipmentSlot], list: List[InventoryItem]): List[InventoryItem] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val slot = iter.next
|
||||
if(slot.Equipment.isEmpty) {
|
||||
if (slot.Equipment.isEmpty) {
|
||||
list.find(item => item.obj.Size == slot.Size) match {
|
||||
case Some(obj) =>
|
||||
val index = list.indexOf(obj)
|
||||
|
|
@ -103,21 +115,20 @@ object Players {
|
|||
case None =>
|
||||
fillEmptyHolsters(iter, list)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fillEmptyHolsters(iter, list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def CertificationToUseExoSuit(player : Player, exosuit : ExoSuitType.Value, subtype : Int) : Boolean = {
|
||||
def CertificationToUseExoSuit(player: Player, exosuit: ExoSuitType.Value, subtype: Int): Boolean = {
|
||||
ExoSuitDefinition.Select(exosuit, player.Faction).Permissions match {
|
||||
case Nil =>
|
||||
true
|
||||
case permissions if subtype != 0 =>
|
||||
val certs = player.Certifications
|
||||
certs.intersect(permissions.toSet).nonEmpty &&
|
||||
certs.intersect(InfantryLoadout.DetermineSubtypeC(subtype)).nonEmpty
|
||||
certs.intersect(InfantryLoadout.DetermineSubtypeC(subtype)).nonEmpty
|
||||
case permissions =>
|
||||
player.Certifications.intersect(permissions.toSet).nonEmpty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,82 +19,97 @@ import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
|||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
class SensorDeployable(cdef : SensorDeployableDefinition) extends ComplexDeployable(cdef)
|
||||
with Hackable
|
||||
with JammableUnit
|
||||
class SensorDeployable(cdef: SensorDeployableDefinition) extends ComplexDeployable(cdef) with Hackable with JammableUnit
|
||||
|
||||
class SensorDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) {
|
||||
class SensorDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
|
||||
Name = "sensor_deployable"
|
||||
DeployCategory = DeployableCategory.Sensors
|
||||
Model = StandardResolutions.SimpleDeployables
|
||||
Packet = new SmallDeployableConverter
|
||||
|
||||
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
obj.Actor = context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
obj.Actor =
|
||||
context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
|
||||
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
|
||||
object SensorDeployableDefinition {
|
||||
def apply(dtype : DeployedItem.Value) : SensorDeployableDefinition = {
|
||||
def apply(dtype: DeployedItem.Value): SensorDeployableDefinition = {
|
||||
new SensorDeployableDefinition(dtype.id)
|
||||
}
|
||||
}
|
||||
|
||||
class SensorDeployableControl(sensor : SensorDeployable) extends Actor
|
||||
with JammableBehavior
|
||||
with DamageableEntity
|
||||
with RepairableEntity {
|
||||
def JammableObject = sensor
|
||||
class SensorDeployableControl(sensor: SensorDeployable)
|
||||
extends Actor
|
||||
with JammableBehavior
|
||||
with DamageableEntity
|
||||
with RepairableEntity {
|
||||
def JammableObject = sensor
|
||||
def DamageableObject = sensor
|
||||
def RepairableObject = sensor
|
||||
|
||||
def receive : Receive = jammableBehavior
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def receive: Receive =
|
||||
jammableBehavior
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override protected def DamageLog(msg : String) : Unit = { }
|
||||
override protected def DamageLog(msg: String): Unit = {}
|
||||
|
||||
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = {
|
||||
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
|
||||
super.DestructionAwareness(target, cause)
|
||||
SensorDeployableControl.DestructionAwareness(sensor, PlanetSideGUID(0))
|
||||
}
|
||||
|
||||
override def StartJammeredSound(target : Any, dur : Int) : Unit = target match {
|
||||
case obj : PlanetSideServerObject if !jammedSound =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1))
|
||||
super.StartJammeredSound(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
|
||||
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
||||
val zone = obj.Zone
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000))
|
||||
super.StartJammeredStatus(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def CancelJammeredSound(target : Any) : Unit = {
|
||||
override def StartJammeredSound(target: Any, dur: Int): Unit =
|
||||
target match {
|
||||
case obj : PlanetSideServerObject if jammedSound =>
|
||||
case obj: PlanetSideServerObject if !jammedSound =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
obj.Zone.Id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1)
|
||||
)
|
||||
super.StartJammeredSound(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
||||
target match {
|
||||
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
||||
val zone = obj.Zone
|
||||
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0))
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.Id,
|
||||
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000)
|
||||
)
|
||||
super.StartJammeredStatus(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def CancelJammeredSound(target: Any): Unit = {
|
||||
target match {
|
||||
case obj: PlanetSideServerObject if jammedSound =>
|
||||
val zone = obj.Zone
|
||||
zone.VehicleEvents ! VehicleServiceMessage(
|
||||
zone.Id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0)
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
super.CancelJammeredSound(target)
|
||||
}
|
||||
|
||||
override def CancelJammeredStatus(target : Any) : Unit = {
|
||||
override def CancelJammeredStatus(target: Any): Unit = {
|
||||
target match {
|
||||
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed =>
|
||||
sensor.Zone.LocalEvents ! LocalServiceMessage(sensor.Zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000))
|
||||
case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
|
||||
sensor.Zone.LocalEvents ! LocalServiceMessage(
|
||||
sensor.Zone.Id,
|
||||
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000)
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
super.CancelJammeredStatus(target)
|
||||
|
|
@ -102,30 +117,33 @@ class SensorDeployableControl(sensor : SensorDeployable) extends Actor
|
|||
}
|
||||
|
||||
object SensorDeployableControl {
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param target na
|
||||
* @param attribution na
|
||||
*/
|
||||
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = {
|
||||
def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
|
||||
Deployables.AnnounceDestroyDeployable(target, Some(1 seconds))
|
||||
val zone = target.Zone
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id,
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.Id,
|
||||
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", target.GUID, false, 1000)
|
||||
)
|
||||
//position the explosion effect near the bulky area of the sensor stalk
|
||||
val ang = target.Orientation
|
||||
val explosionPos = {
|
||||
val pos = target.Position
|
||||
val explosionPos = {
|
||||
val pos = target.Position
|
||||
val yRadians = ang.y.toRadians
|
||||
val d = Vector3.Rz(Vector3(0, 0.875f, 0), ang.z) * math.sin(yRadians).toFloat
|
||||
val d = Vector3.Rz(Vector3(0, 0.875f, 0), ang.z) * math.sin(yRadians).toFloat
|
||||
Vector3(
|
||||
pos.x + d.x,
|
||||
pos.y + d.y,
|
||||
pos.z + math.cos(yRadians).toFloat * 0.875f
|
||||
)
|
||||
}
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id,
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.Id,
|
||||
LocalAction.TriggerEffectLocation(Service.defaultPlayerGUID, "motion_sensor_destroyed", explosionPos, ang)
|
||||
)
|
||||
//TODO replaced by an alternate model (charred stub)?
|
||||
|
|
|
|||
|
|
@ -17,38 +17,42 @@ import net.psforever.types.PlanetSideGUID
|
|||
import services.Service
|
||||
import services.vehicle.{VehicleAction, VehicleServiceMessage}
|
||||
|
||||
class ShieldGeneratorDeployable(cdef : ShieldGeneratorDefinition) extends ComplexDeployable(cdef)
|
||||
with Hackable
|
||||
with JammableUnit
|
||||
class ShieldGeneratorDeployable(cdef: ShieldGeneratorDefinition)
|
||||
extends ComplexDeployable(cdef)
|
||||
with Hackable
|
||||
with JammableUnit
|
||||
|
||||
class ShieldGeneratorDefinition extends ComplexDeployableDefinition(240) {
|
||||
Packet = new ShieldGeneratorConverter
|
||||
DeployCategory = DeployableCategory.ShieldGenerators
|
||||
|
||||
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
obj.Actor = context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
obj.Actor =
|
||||
context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
|
||||
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
|
||||
class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
|
||||
with JammableBehavior
|
||||
with DamageableEntity
|
||||
with RepairableEntity {
|
||||
def JammableObject = gen
|
||||
def DamageableObject = gen
|
||||
def RepairableObject = gen
|
||||
private var handleDamageToShields : Boolean = false
|
||||
class ShieldGeneratorControl(gen: ShieldGeneratorDeployable)
|
||||
extends Actor
|
||||
with JammableBehavior
|
||||
with DamageableEntity
|
||||
with RepairableEntity {
|
||||
def JammableObject = gen
|
||||
def DamageableObject = gen
|
||||
def RepairableObject = gen
|
||||
private var handleDamageToShields: Boolean = false
|
||||
|
||||
def receive : Receive = jammableBehavior
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def receive: Receive =
|
||||
jammableBehavior
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
/**
|
||||
* The shield generator has two upgrade paths - blocking projectiles, and providing ammunition like a terminal.
|
||||
|
|
@ -59,44 +63,48 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
|
|||
* @param player the user of the nano dispenser tool
|
||||
* @param item the nano dispenser tool
|
||||
*/
|
||||
override def CanBeRepairedByNanoDispenser(player : Player, item : Tool) : Unit = {
|
||||
if(gen.CanRepair) {
|
||||
override def CanBeRepairedByNanoDispenser(player: Player, item: Tool): Unit = {
|
||||
if (gen.CanRepair) {
|
||||
super.CanBeRepairedByNanoDispenser(player, item)
|
||||
}
|
||||
else if(!gen.Destroyed) {
|
||||
} else if (!gen.Destroyed) {
|
||||
//TODO reinforced shield upgrade not implemented yet
|
||||
//TODO ammunition supply upgrade not implemented yet
|
||||
}
|
||||
}
|
||||
|
||||
override protected def PerformDamage(target : Damageable.Target, applyDamageTo : ResolutionCalculations.Output) : Unit = {
|
||||
val originalHealth = gen.Health
|
||||
override protected def PerformDamage(
|
||||
target: Damageable.Target,
|
||||
applyDamageTo: ResolutionCalculations.Output
|
||||
): Unit = {
|
||||
val originalHealth = gen.Health
|
||||
val originalShields = gen.Shields
|
||||
val cause = applyDamageTo(target)
|
||||
val health = gen.Health
|
||||
val shields = gen.Shields
|
||||
val damageToHealth = originalHealth - health
|
||||
val cause = applyDamageTo(target)
|
||||
val health = gen.Health
|
||||
val shields = gen.Shields
|
||||
val damageToHealth = originalHealth - health
|
||||
val damageToShields = originalShields - shields
|
||||
val damage = damageToHealth + damageToShields
|
||||
if(WillAffectTarget(target, damage, cause)) {
|
||||
val damage = damageToHealth + damageToShields
|
||||
if (WillAffectTarget(target, damage, cause)) {
|
||||
target.History(cause)
|
||||
DamageLog(target,s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields")
|
||||
DamageLog(
|
||||
target,
|
||||
s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields"
|
||||
)
|
||||
handleDamageToShields = damageToShields > 0
|
||||
HandleDamage(target, cause, damageToHealth)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
gen.Health = originalHealth
|
||||
gen.Shields = originalShields
|
||||
}
|
||||
}
|
||||
|
||||
override protected def DamageAwareness(target : Damageable.Target, cause : ResolvedProjectile, amount : Int) : Unit = {
|
||||
override protected def DamageAwareness(target: Damageable.Target, cause: ResolvedProjectile, amount: Int): Unit = {
|
||||
super.DamageAwareness(target, cause, amount)
|
||||
ShieldGeneratorControl.DamageAwareness(gen, cause, handleDamageToShields)
|
||||
handleDamageToShields = false
|
||||
}
|
||||
|
||||
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = {
|
||||
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
|
||||
super.DestructionAwareness(target, cause)
|
||||
ShieldGeneratorControl.DestructionAwareness(gen, PlanetSideGUID(0))
|
||||
}
|
||||
|
|
@ -105,21 +113,28 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
|
|||
while the shield generator is technically a supported jammable target, how that works is currently unknown
|
||||
check the object definition for proper feature activation
|
||||
*/
|
||||
override def StartJammeredSound(target : Any, dur : Int) : Unit = { }
|
||||
override def StartJammeredSound(target: Any, dur: Int): Unit = {}
|
||||
|
||||
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
|
||||
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1))
|
||||
super.StartJammeredStatus(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def CancelJammeredSound(target : Any) : Unit = { }
|
||||
|
||||
override def CancelJammeredStatus(target : Any) : Unit = {
|
||||
override def StartJammeredStatus(target: Any, dur: Int): Unit =
|
||||
target match {
|
||||
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0))
|
||||
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
obj.Zone.Id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)
|
||||
)
|
||||
super.StartJammeredStatus(obj, dur)
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override def CancelJammeredSound(target: Any): Unit = {}
|
||||
|
||||
override def CancelJammeredStatus(target: Any): Unit = {
|
||||
target match {
|
||||
case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
|
||||
obj.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
obj.Zone.Id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0)
|
||||
)
|
||||
case _ => ;
|
||||
}
|
||||
super.CancelJammeredStatus(target)
|
||||
|
|
@ -127,17 +142,21 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
|
|||
}
|
||||
|
||||
object ShieldGeneratorControl {
|
||||
|
||||
/**
|
||||
* na
|
||||
* @param target na
|
||||
* @param cause na
|
||||
* @param damageToShields na
|
||||
*/
|
||||
def DamageAwareness(target : ShieldGeneratorDeployable, cause : ResolvedProjectile, damageToShields : Boolean) : Unit = {
|
||||
def DamageAwareness(target: ShieldGeneratorDeployable, cause: ResolvedProjectile, damageToShields: Boolean): Unit = {
|
||||
//shields
|
||||
if(damageToShields) {
|
||||
if (damageToShields) {
|
||||
val zone = target.Zone
|
||||
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields))
|
||||
zone.VehicleEvents ! VehicleServiceMessage(
|
||||
zone.Id,
|
||||
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +165,7 @@ object ShieldGeneratorControl {
|
|||
* @param target na
|
||||
* @param attribution na
|
||||
*/
|
||||
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = {
|
||||
def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
|
||||
Deployables.AnnounceDestroyDeployable(target, None)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ package net.psforever.objects
|
|||
import net.psforever.objects.definition.SimpleItemDefinition
|
||||
import net.psforever.objects.equipment.Equipment
|
||||
|
||||
class SimpleItem(private val simpDef : SimpleItemDefinition) extends Equipment {
|
||||
def Definition : SimpleItemDefinition = simpDef
|
||||
class SimpleItem(private val simpDef: SimpleItemDefinition) extends Equipment {
|
||||
def Definition: SimpleItemDefinition = simpDef
|
||||
}
|
||||
|
||||
object SimpleItem {
|
||||
def apply(simpDef : SimpleItemDefinition) : SimpleItem = {
|
||||
def apply(simpDef: SimpleItemDefinition): SimpleItem = {
|
||||
new SimpleItem(simpDef)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,27 +8,31 @@ import net.psforever.types.{PlanetSideGUID, Vector3}
|
|||
import scala.collection.mutable
|
||||
|
||||
trait SpawnPoint {
|
||||
psso : PlanetSideServerObject =>
|
||||
psso: PlanetSideServerObject =>
|
||||
|
||||
/**
|
||||
* An element of the contract of `PlanetSideServerObject`;
|
||||
* but, this makes it visible to a `SpawnPoint` object without casting.
|
||||
* @see `Identifiable.GUID`
|
||||
*/
|
||||
def GUID : PlanetSideGUID
|
||||
def GUID: PlanetSideGUID
|
||||
|
||||
/**
|
||||
* An element of the contract of `PlanetSideServerObject`;
|
||||
* but, this makes it visible to a `SpawnPoint` object without casting.
|
||||
* @see `WorldEntity.GUID`
|
||||
* @see `SpecificPoint`
|
||||
*/
|
||||
def Position : Vector3
|
||||
def Position: Vector3
|
||||
|
||||
/**
|
||||
* An element of the contract of `PlanetSideServerObject`;
|
||||
* but, this makes it visible to a `SpawnPoint` object without casting.
|
||||
* @see `WorldEntity.GUID`
|
||||
* @see `SpecificPoint`
|
||||
*/
|
||||
def Orientation : Vector3
|
||||
def Orientation: Vector3
|
||||
|
||||
/**
|
||||
* An element of an unspoken contract with `Amenity`.
|
||||
* While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class,
|
||||
|
|
@ -36,16 +40,17 @@ trait SpawnPoint {
|
|||
* This should generally be themselves.
|
||||
* @see `Amenity.Owner`
|
||||
*/
|
||||
def Owner : PlanetSideServerObject
|
||||
def Owner: PlanetSideServerObject
|
||||
|
||||
/**
|
||||
* An element of the contract of `PlanetSideServerObject`;
|
||||
* but, this makes it visible to a `SpawnPoint` object without casting.
|
||||
* @see `PlanetSideGameObject.Definition`
|
||||
* @see `SpecificPoint`
|
||||
*/
|
||||
def Definition : ObjectDefinition with SpawnPointDefinition
|
||||
def Definition: ObjectDefinition with SpawnPointDefinition
|
||||
|
||||
def Offline : Boolean = psso.Destroyed
|
||||
def Offline: Boolean = psso.Destroyed
|
||||
|
||||
/**
|
||||
* Determine a specific position and orientation in which to spawn the target.
|
||||
|
|
@ -53,9 +58,9 @@ trait SpawnPoint {
|
|||
* the first represents the game world position of spawning;
|
||||
* the second represents the game world direction of spawning
|
||||
*/
|
||||
def SpecificPoint(target : PlanetSideGameObject) : (Vector3, Vector3) = {
|
||||
def SpecificPoint(target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
psso.Definition match {
|
||||
case d : SpawnPointDefinition =>
|
||||
case d: SpawnPointDefinition =>
|
||||
d.SpecificPoint(this, target)
|
||||
case _ =>
|
||||
SpawnPoint.Default(this, target)
|
||||
|
|
@ -64,49 +69,53 @@ trait SpawnPoint {
|
|||
}
|
||||
|
||||
object SpawnPoint {
|
||||
def Default(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (obj.Position, obj.Orientation)
|
||||
def Default(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = (obj.Position, obj.Orientation)
|
||||
|
||||
def Tube(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (
|
||||
obj.Position + Vector3.z(1.5f),
|
||||
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
|
||||
)
|
||||
|
||||
def AMS(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
|
||||
//position the player alongside either of the AMS's terminals, facing away from it
|
||||
val ori = obj.Orientation
|
||||
val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
|
||||
val x = ori.x
|
||||
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
|
||||
val z = ori.z
|
||||
val zrot = (z + 90) % 360
|
||||
val zrad = math.toRadians(zrot)
|
||||
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
|
||||
def Tube(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) =
|
||||
(
|
||||
obj.Position + shift + (if(x >= 330) { //ams leaning to the left
|
||||
Vector3.z(xsin)
|
||||
}
|
||||
else { //ams leaning to the right
|
||||
Vector3.z(-xsin)
|
||||
}),
|
||||
if(side == 1) {
|
||||
obj.Position + Vector3.z(1.5f),
|
||||
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
|
||||
)
|
||||
|
||||
def AMS(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
//position the player alongside either of the AMS's terminals, facing away from it
|
||||
val ori = obj.Orientation
|
||||
val side = if (System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
|
||||
val x = ori.x
|
||||
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
|
||||
val z = ori.z
|
||||
val zrot = (z + 90) % 360
|
||||
val zrad = math.toRadians(zrot)
|
||||
val shift = Vector3(
|
||||
math.sin(zrad).toFloat,
|
||||
math.cos(zrad).toFloat,
|
||||
0
|
||||
) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
|
||||
(
|
||||
obj.Position + shift + (if (x >= 330) { //ams leaning to the left
|
||||
Vector3.z(xsin)
|
||||
} else { //ams leaning to the right
|
||||
Vector3.z(-xsin)
|
||||
}),
|
||||
if (side == 1) {
|
||||
Vector3.z(zrot)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Vector3.z((z - 90) % 360)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
def Gate(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
|
||||
def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
|
||||
obj.Definition match {
|
||||
case d : SpawnPointDefinition =>
|
||||
val ori = target.Orientation
|
||||
case d: SpawnPointDefinition =>
|
||||
val ori = target.Orientation
|
||||
val zrad = math.toRadians(ori.z)
|
||||
val radius = scala.math.random.toFloat * d.UseRadius/2 + 20f //20 is definitely outside of the gating energy field
|
||||
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
|
||||
val radius =
|
||||
scala.math.random.toFloat * d.UseRadius / 2 + 20f //20 is definitely outside of the gating energy field
|
||||
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
|
||||
val altitudeShift = target.Definition match {
|
||||
case vdef : VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
|
||||
Vector3.z(scala.math.random.toFloat * d.UseRadius/4 + 20f)
|
||||
case vdef: VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
|
||||
Vector3.z(scala.math.random.toFloat * d.UseRadius / 4 + 20f)
|
||||
case _ =>
|
||||
Vector3.Zero
|
||||
}
|
||||
|
|
@ -118,46 +127,45 @@ object SpawnPoint {
|
|||
}
|
||||
|
||||
trait SpawnPointDefinition {
|
||||
private var radius : Float = 0f //m
|
||||
private var delay : Long = 0 //s
|
||||
private var noWarp : Option[mutable.Set[VehicleDefinition]] = None
|
||||
private var spawningFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
|
||||
private var radius: Float = 0f //m
|
||||
private var delay: Long = 0 //s
|
||||
private var noWarp: Option[mutable.Set[VehicleDefinition]] = None
|
||||
private var spawningFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
|
||||
|
||||
def UseRadius : Float = radius
|
||||
def UseRadius: Float = radius
|
||||
|
||||
def UseRadius_=(rad : Float) : Float = {
|
||||
def UseRadius_=(rad: Float): Float = {
|
||||
radius = rad
|
||||
UseRadius
|
||||
}
|
||||
|
||||
def Delay : Long = delay
|
||||
def Delay: Long = delay
|
||||
|
||||
def Delay_=(toDelay : Long) : Long = {
|
||||
def Delay_=(toDelay: Long): Long = {
|
||||
delay = toDelay
|
||||
Delay
|
||||
}
|
||||
|
||||
def VehicleAllowance : Boolean = noWarp.isDefined
|
||||
def VehicleAllowance: Boolean = noWarp.isDefined
|
||||
|
||||
def VehicleAllowance_=(allow : Boolean) : Boolean = {
|
||||
if(allow && noWarp.isEmpty) {
|
||||
def VehicleAllowance_=(allow: Boolean): Boolean = {
|
||||
if (allow && noWarp.isEmpty) {
|
||||
noWarp = Some(mutable.Set.empty[VehicleDefinition])
|
||||
}
|
||||
else if(!allow && noWarp.isDefined) {
|
||||
} else if (!allow && noWarp.isDefined) {
|
||||
noWarp = None
|
||||
}
|
||||
VehicleAllowance
|
||||
}
|
||||
|
||||
def NoWarp : mutable.Set[VehicleDefinition] = {
|
||||
def NoWarp: mutable.Set[VehicleDefinition] = {
|
||||
noWarp.getOrElse(mutable.Set.empty[VehicleDefinition])
|
||||
}
|
||||
|
||||
def SpecificPointFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
|
||||
def SpecificPointFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
|
||||
|
||||
def SpecificPointFunc_=(func : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)) : Unit = {
|
||||
def SpecificPointFunc_=(func: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)): Unit = {
|
||||
spawningFunc = func
|
||||
}
|
||||
|
||||
def SpecificPoint(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = spawningFunc(obj, target)
|
||||
def SpecificPoint(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = spawningFunc(obj, target)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ package net.psforever.objects
|
|||
import net.psforever.objects.ce.TelepadLike
|
||||
import net.psforever.objects.definition.ConstructionItemDefinition
|
||||
|
||||
class Telepad(private val cdef : ConstructionItemDefinition) extends ConstructionItem(cdef)
|
||||
with TelepadLike
|
||||
class Telepad(private val cdef: ConstructionItemDefinition) extends ConstructionItem(cdef) with TelepadLike
|
||||
|
||||
object Telepad {
|
||||
def apply(cdef : ConstructionItemDefinition) : Telepad = {
|
||||
def apply(cdef: ConstructionItemDefinition): Telepad = {
|
||||
new Telepad(cdef)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,4 @@ package net.psforever.objects
|
|||
import net.psforever.objects.ce.{SimpleDeployable, TelepadLike}
|
||||
import net.psforever.objects.definition.SimpleDeployableDefinition
|
||||
|
||||
class TelepadDeployable(ddef : SimpleDeployableDefinition) extends SimpleDeployable(ddef)
|
||||
with TelepadLike
|
||||
class TelepadDeployable(ddef: SimpleDeployableDefinition) extends SimpleDeployable(ddef) with TelepadLike
|
||||
|
|
|
|||
|
|
@ -17,77 +17,79 @@ import scala.annotation.tailrec
|
|||
* Some weapons Chainblade have ammunition but do not consume it.
|
||||
* @param toolDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
|
||||
*/
|
||||
class Tool(private val toolDef : ToolDefinition) extends Equipment
|
||||
with FireModeSwitch[FireModeDefinition]
|
||||
with JammableUnit {
|
||||
class Tool(private val toolDef: ToolDefinition)
|
||||
extends Equipment
|
||||
with FireModeSwitch[FireModeDefinition]
|
||||
with JammableUnit {
|
||||
|
||||
/** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
|
||||
private var fireModeIndex : Int = toolDef.DefaultFireModeIndex
|
||||
private var fireModeIndex: Int = toolDef.DefaultFireModeIndex
|
||||
|
||||
/** current ammunition slot being used by this fire mode */
|
||||
private var ammoSlots : List[Tool.FireModeSlot] = List.empty
|
||||
var lastDischarge : Long = 0
|
||||
private var ammoSlots: List[Tool.FireModeSlot] = List.empty
|
||||
var lastDischarge: Long = 0
|
||||
|
||||
Tool.LoadDefinition(this)
|
||||
|
||||
def FireModeIndex : Int = fireModeIndex
|
||||
def FireModeIndex: Int = fireModeIndex
|
||||
|
||||
def FireModeIndex_=(index : Int) : Int = {
|
||||
def FireModeIndex_=(index: Int): Int = {
|
||||
fireModeIndex = index % Definition.FireModes.length
|
||||
FireModeIndex
|
||||
}
|
||||
|
||||
def FireMode : FireModeDefinition = Definition.FireModes(fireModeIndex)
|
||||
def FireMode: FireModeDefinition = Definition.FireModes(fireModeIndex)
|
||||
|
||||
def NextFireMode : FireModeDefinition = {
|
||||
def NextFireMode: FireModeDefinition = {
|
||||
FireModeIndex = Definition.NextFireModeIndex(FireModeIndex)
|
||||
AmmoSlot.Chamber = FireMode.Chamber
|
||||
FireMode
|
||||
}
|
||||
|
||||
def ToFireMode : Int = Definition.NextFireModeIndex(FireModeIndex)
|
||||
def ToFireMode: Int = Definition.NextFireModeIndex(FireModeIndex)
|
||||
|
||||
def ToFireMode_=(index : Int) : FireModeDefinition = {
|
||||
def ToFireMode_=(index: Int): FireModeDefinition = {
|
||||
FireModeIndex = index
|
||||
AmmoSlot.Chamber = FireMode.Chamber
|
||||
FireMode
|
||||
}
|
||||
|
||||
def AmmoTypeIndex : Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
|
||||
def AmmoTypeIndex: Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
|
||||
|
||||
def AmmoTypeIndex_=(index : Int) : Int = {
|
||||
def AmmoTypeIndex_=(index: Int): Int = {
|
||||
AmmoSlot.AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length
|
||||
AmmoTypeIndex
|
||||
}
|
||||
|
||||
def AmmoType : Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType
|
||||
def AmmoType: Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType
|
||||
|
||||
def NextAmmoType : Ammo.Value = {
|
||||
def NextAmmoType: Ammo.Value = {
|
||||
AmmoSlot.AmmoTypeIndex = AmmoSlot.AmmoTypeIndex + 1
|
||||
AmmoType
|
||||
}
|
||||
|
||||
def Projectile : ProjectileDefinition = {
|
||||
def Projectile: ProjectileDefinition = {
|
||||
Definition.ProjectileTypes({
|
||||
val projIndices = FireMode.ProjectileTypeIndices
|
||||
if(projIndices.isEmpty) {
|
||||
if (projIndices.isEmpty) {
|
||||
AmmoTypeIndex //e.g., bullet_9mm -> bullet_9mm_projectile, bullet_9mm_AP -> bullet_9mm_AP_projectile
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
projIndices(AmmoSlot.AmmoTypeIndex) //e.g., pulsar: f.mode1 -> pulsar_projectile, f.mode2 = pulsar_ap_projectile
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
def ProjectileType : Projectiles.Value = Projectile.ProjectileType
|
||||
def ProjectileType: Projectiles.Value = Projectile.ProjectileType
|
||||
|
||||
def Magazine : Int = AmmoSlot.Magazine
|
||||
def Magazine: Int = AmmoSlot.Magazine
|
||||
|
||||
def Magazine_=(mag : Int) : Int = {
|
||||
def Magazine_=(mag: Int): Int = {
|
||||
//AmmoSlot.Magazine = Math.min(Math.max(0, mag), MaxMagazine)
|
||||
AmmoSlot.Magazine = Math.max(0, mag)
|
||||
Magazine
|
||||
}
|
||||
|
||||
def MaxMagazine : Int = {
|
||||
def MaxMagazine: Int = {
|
||||
val fmode = FireMode
|
||||
fmode.CustomMagazine.get(AmmoType) match {
|
||||
case Some(magSize) =>
|
||||
|
|
@ -97,30 +99,30 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment
|
|||
}
|
||||
}
|
||||
|
||||
def Discharge(rounds : Option[Int] = None) : Int = {
|
||||
def Discharge(rounds: Option[Int] = None): Int = {
|
||||
lastDischarge = System.nanoTime()
|
||||
Magazine = FireMode.Discharge(this, rounds)
|
||||
}
|
||||
|
||||
def LastDischarge : Long = {
|
||||
def LastDischarge: Long = {
|
||||
lastDischarge
|
||||
}
|
||||
|
||||
def AmmoSlot : Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
|
||||
def AmmoSlot: Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
|
||||
|
||||
def AmmoSlots : List[Tool.FireModeSlot] = ammoSlots
|
||||
def AmmoSlots: List[Tool.FireModeSlot] = ammoSlots
|
||||
|
||||
def MaxAmmoSlot : Int = ammoSlots.length
|
||||
def MaxAmmoSlot: Int = ammoSlots.length
|
||||
|
||||
def Definition : ToolDefinition = toolDef
|
||||
def Definition: ToolDefinition = toolDef
|
||||
|
||||
override def toString : String = Tool.toString(this)
|
||||
override def toString: String = Tool.toString(this)
|
||||
}
|
||||
|
||||
//AmmoType = Definition.AmmoTypes( (Definition.FireModes(fireModeIndex)).AmmoTypeIndices( (ammoSlots((Definition.FireModes(fireModeIndex)).AmmoSlotIndex)).AmmoTypeIndex) ).AmmoType
|
||||
|
||||
object Tool {
|
||||
def apply(toolDef : ToolDefinition) : Tool = {
|
||||
def apply(toolDef: ToolDefinition): Tool = {
|
||||
new Tool(toolDef)
|
||||
}
|
||||
|
||||
|
|
@ -128,28 +130,34 @@ object Tool {
|
|||
* Use the `*Definition` that was provided to this object to initialize its fields and settings.
|
||||
* @param tool the `Tool` being initialized
|
||||
*/
|
||||
def LoadDefinition(tool : Tool) : Unit = {
|
||||
val tdef : ToolDefinition = tool.Definition
|
||||
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
|
||||
def LoadDefinition(tool: Tool): Unit = {
|
||||
val tdef: ToolDefinition = tool.Definition
|
||||
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
|
||||
tool.ammoSlots = buildFireModes(tdef, (0 to maxSlot).iterator, tdef.FireModes.toList)
|
||||
}
|
||||
|
||||
@tailrec private def buildFireModes(tdef : ToolDefinition, iter : Iterator[Int], fmodes : List[FireModeDefinition], list : List[FireModeSlot] = Nil) : List[FireModeSlot] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def buildFireModes(
|
||||
tdef: ToolDefinition,
|
||||
iter: Iterator[Int],
|
||||
fmodes: List[FireModeDefinition],
|
||||
list: List[FireModeSlot] = Nil
|
||||
): List[FireModeSlot] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val index = iter.next
|
||||
fmodes.filter(fmode => fmode.AmmoSlotIndex == index) match {
|
||||
case fmode :: _ =>
|
||||
buildFireModes(tdef, iter, fmodes, list :+ new FireModeSlot(tdef, fmode))
|
||||
case Nil =>
|
||||
throw new IllegalArgumentException(s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip")
|
||||
throw new IllegalArgumentException(
|
||||
s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def toString(obj : Tool) : String = {
|
||||
def toString(obj: Tool): String = {
|
||||
s"${obj.Definition.Name} (mode=${obj.FireModeIndex}-${obj.AmmoType})(${obj.Magazine}/${obj.MaxMagazine})"
|
||||
}
|
||||
|
||||
|
|
@ -166,24 +174,26 @@ object Tool {
|
|||
* two exclusive groups of ammunition divided into 2 cycled types and 4 cycled types -
|
||||
* is an example of a weapon that benefits from this implementation.
|
||||
*/
|
||||
class FireModeSlot(private val tdef : ToolDefinition, private val fdef : FireModeDefinition) {
|
||||
class FireModeSlot(private val tdef: ToolDefinition, private val fdef: FireModeDefinition) {
|
||||
|
||||
/**
|
||||
* if this fire mode has multiple types of ammunition
|
||||
* this is the index of the fire mode's ammo List, not a reference to the tool's ammo List
|
||||
*/
|
||||
private var ammoTypeIndex : Int = 0
|
||||
private var ammoTypeIndex: Int = 0
|
||||
|
||||
/** a reference to the actual `AmmoBox` of this slot */
|
||||
private var box : AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine)
|
||||
private var chamber = fdef.Chamber
|
||||
private var box: AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine)
|
||||
private var chamber = fdef.Chamber
|
||||
|
||||
def AmmoTypeIndex : Int = ammoTypeIndex
|
||||
def AmmoTypeIndex: Int = ammoTypeIndex
|
||||
|
||||
def AmmoTypeIndex_=(index : Int) : Int = {
|
||||
def AmmoTypeIndex_=(index: Int): Int = {
|
||||
ammoTypeIndex = index % fdef.AmmoTypeIndices.length
|
||||
AmmoTypeIndex
|
||||
}
|
||||
|
||||
private def AmmoDefinition : AmmoBoxDefinition = {
|
||||
private def AmmoDefinition: AmmoBoxDefinition = {
|
||||
tdef.AmmoTypes(fdef.AmmoTypeIndices(ammoTypeIndex))
|
||||
}
|
||||
|
||||
|
|
@ -193,40 +203,39 @@ object Tool {
|
|||
* Generally, convert from this index, to the index in the fire mode's ammunition list, to the index in the `ToolDefinition`'s ammunition list.
|
||||
* @return the `Ammo` type that should be loaded into the magazine right now
|
||||
*/
|
||||
def AmmoType : Ammo.Value = AmmoDefinition.AmmoType
|
||||
def AmmoType: Ammo.Value = AmmoDefinition.AmmoType
|
||||
|
||||
def AllAmmoTypes : List[Ammo.Value] = {
|
||||
def AllAmmoTypes: List[Ammo.Value] = {
|
||||
fdef.AmmoTypeIndices.map(index => tdef.AmmoTypes(fdef.AmmoTypeIndices(index)).AmmoType).toList
|
||||
}
|
||||
|
||||
def Magazine : Int = box.Capacity
|
||||
def Magazine: Int = box.Capacity
|
||||
|
||||
def Magazine_=(mag : Int) : Int = {
|
||||
def Magazine_=(mag: Int): Int = {
|
||||
box.Capacity = mag
|
||||
Magazine
|
||||
}
|
||||
|
||||
def Chamber : Int = chamber
|
||||
def Chamber: Int = chamber
|
||||
|
||||
def Chamber_=(chmbr : Int) : Int = {
|
||||
def Chamber_=(chmbr: Int): Int = {
|
||||
chamber = math.min(math.max(0, chmbr), fdef.Chamber)
|
||||
Chamber
|
||||
}
|
||||
|
||||
def Box : AmmoBox = box
|
||||
def Box: AmmoBox = box
|
||||
|
||||
def Box_=(toBox : AmmoBox) : Option[AmmoBox] = {
|
||||
if(toBox.AmmoType == AmmoType) {
|
||||
def Box_=(toBox: AmmoBox): Option[AmmoBox] = {
|
||||
if (toBox.AmmoType == AmmoType) {
|
||||
box = toBox
|
||||
Some(Box)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def Tool : ToolDefinition = tdef
|
||||
def Tool: ToolDefinition = tdef
|
||||
|
||||
def Definition : FireModeDefinition = fdef
|
||||
def Definition: FireModeDefinition = fdef
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,40 +11,39 @@ import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
|
|||
import net.psforever.objects.serverobject.repair.RepairableEntity
|
||||
import net.psforever.objects.vital.StandardResolutions
|
||||
|
||||
class TrapDeployable(cdef : TrapDeployableDefinition) extends ComplexDeployable(cdef)
|
||||
class TrapDeployable(cdef: TrapDeployableDefinition) extends ComplexDeployable(cdef)
|
||||
|
||||
class TrapDeployableDefinition(objectId : Int) extends ComplexDeployableDefinition(objectId) {
|
||||
class TrapDeployableDefinition(objectId: Int) extends ComplexDeployableDefinition(objectId) {
|
||||
Model = StandardResolutions.SimpleDeployables
|
||||
Packet = new TRAPConverter
|
||||
|
||||
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
obj.Actor = context.actorOf(Props(classOf[TrapDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
|
||||
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
|
||||
object TrapDeployableDefinition {
|
||||
def apply(dtype : DeployedItem.Value) : TrapDeployableDefinition = {
|
||||
def apply(dtype: DeployedItem.Value): TrapDeployableDefinition = {
|
||||
new TrapDeployableDefinition(dtype.id)
|
||||
}
|
||||
}
|
||||
|
||||
class TrapDeployableControl(trap : TrapDeployable) extends Actor
|
||||
with DamageableEntity
|
||||
with RepairableEntity {
|
||||
class TrapDeployableControl(trap: TrapDeployable) extends Actor with DamageableEntity with RepairableEntity {
|
||||
def DamageableObject = trap
|
||||
def RepairableObject = trap
|
||||
|
||||
def receive : Receive = takesDamage
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ =>
|
||||
}
|
||||
def receive: Receive =
|
||||
takesDamage
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ =>
|
||||
}
|
||||
|
||||
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = {
|
||||
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
|
||||
super.DestructionAwareness(target, cause)
|
||||
Deployables.AnnounceDestroyDeployable(trap, None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,19 +17,21 @@ import net.psforever.objects.serverobject.repair.RepairableWeaponTurret
|
|||
import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret}
|
||||
import net.psforever.objects.vital.{StandardResolutions, StandardVehicleDamage, StandardVehicleResistance}
|
||||
|
||||
class TurretDeployable(tdef : TurretDeployableDefinition) extends ComplexDeployable(tdef)
|
||||
with WeaponTurret
|
||||
with JammableUnit
|
||||
with Hackable {
|
||||
class TurretDeployable(tdef: TurretDeployableDefinition)
|
||||
extends ComplexDeployable(tdef)
|
||||
with WeaponTurret
|
||||
with JammableUnit
|
||||
with Hackable {
|
||||
WeaponTurret.LoadDefinition(this)
|
||||
|
||||
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
|
||||
def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
|
||||
|
||||
override def Definition = tdef
|
||||
}
|
||||
|
||||
class TurretDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId)
|
||||
with TurretDefinition {
|
||||
class TurretDeployableDefinition(private val objectId: Int)
|
||||
extends ComplexDeployableDefinition(objectId)
|
||||
with TurretDefinition {
|
||||
Name = "turret_deployable"
|
||||
Packet = new SmallTurretConverter
|
||||
DamageUsing = StandardVehicleDamage
|
||||
|
|
@ -37,51 +39,53 @@ class TurretDeployableDefinition(private val objectId : Int) extends ComplexDepl
|
|||
Model = StandardResolutions.FacilityTurrets
|
||||
|
||||
//override to clarify inheritance conflict
|
||||
override def MaxHealth : Int = super[ComplexDeployableDefinition].MaxHealth
|
||||
override def MaxHealth: Int = super[ComplexDeployableDefinition].MaxHealth
|
||||
//override to clarify inheritance conflict
|
||||
override def MaxHealth_=(max : Int) : Int = super[ComplexDeployableDefinition].MaxHealth_=(max)
|
||||
override def MaxHealth_=(max: Int): Int = super[ComplexDeployableDefinition].MaxHealth_=(max)
|
||||
|
||||
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
obj.Actor = context.actorOf(Props(classOf[TurretControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
|
||||
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
|
||||
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
|
||||
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
|
||||
}
|
||||
}
|
||||
|
||||
object TurretDeployableDefinition {
|
||||
def apply(dtype : DeployedItem.Value) : TurretDeployableDefinition = {
|
||||
def apply(dtype: DeployedItem.Value): TurretDeployableDefinition = {
|
||||
new TurretDeployableDefinition(dtype.id)
|
||||
}
|
||||
}
|
||||
|
||||
/** control actors */
|
||||
|
||||
class TurretControl(turret : TurretDeployable) extends Actor
|
||||
with FactionAffinityBehavior.Check
|
||||
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
|
||||
with MountableBehavior.TurretMount
|
||||
with MountableBehavior.Dismount
|
||||
with DamageableWeaponTurret
|
||||
with RepairableWeaponTurret {
|
||||
def MountableObject = turret
|
||||
def JammableObject = turret
|
||||
def FactionObject = turret
|
||||
class TurretControl(turret: TurretDeployable)
|
||||
extends Actor
|
||||
with FactionAffinityBehavior.Check
|
||||
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
|
||||
with MountableBehavior.TurretMount
|
||||
with MountableBehavior.Dismount
|
||||
with DamageableWeaponTurret
|
||||
with RepairableWeaponTurret {
|
||||
def MountableObject = turret
|
||||
def JammableObject = turret
|
||||
def FactionObject = turret
|
||||
def DamageableObject = turret
|
||||
def RepairableObject = turret
|
||||
|
||||
def receive : Receive = checkBehavior
|
||||
.orElse(jammableBehavior)
|
||||
.orElse(mountBehavior)
|
||||
.orElse(dismountBehavior)
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
def receive: Receive =
|
||||
checkBehavior
|
||||
.orElse(jammableBehavior)
|
||||
.orElse(mountBehavior)
|
||||
.orElse(dismountBehavior)
|
||||
.orElse(takesDamage)
|
||||
.orElse(canBeRepairedByNanoDispenser)
|
||||
.orElse {
|
||||
case _ => ;
|
||||
}
|
||||
|
||||
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = {
|
||||
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
|
||||
super.DestructionAwareness(target, cause)
|
||||
Deployables.AnnounceDestroyDeployable(turret, None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,45 +66,48 @@ import scala.util.{Success, Try}
|
|||
* stores and unloads pertinent information about the `Vehicle`'s configuration;
|
||||
* used in the initialization process (`loadVehicleDefinition`)
|
||||
*/
|
||||
class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
||||
with Hackable
|
||||
with FactionAffinity
|
||||
with Mountable
|
||||
with MountedWeapons
|
||||
with Deployment
|
||||
with Vitality
|
||||
with OwnableByPlayer
|
||||
with StandardResistanceProfile
|
||||
with JammableUnit
|
||||
with Container {
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var shields : Int = 0
|
||||
private var decal : Int = 0
|
||||
private var trunkAccess : Option[PlanetSideGUID] = None
|
||||
private var jammered : Boolean = false
|
||||
private var cloaked : Boolean = false
|
||||
private var flying : Boolean = false
|
||||
private var ntuCapacitor : Int = 0
|
||||
private var capacitor : Int = 0
|
||||
class Vehicle(private val vehicleDef: VehicleDefinition)
|
||||
extends AmenityOwner
|
||||
with Hackable
|
||||
with FactionAffinity
|
||||
with Mountable
|
||||
with MountedWeapons
|
||||
with Deployment
|
||||
with Vitality
|
||||
with OwnableByPlayer
|
||||
with StandardResistanceProfile
|
||||
with JammableUnit
|
||||
with Container {
|
||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
private var shields: Int = 0
|
||||
private var decal: Int = 0
|
||||
private var trunkAccess: Option[PlanetSideGUID] = None
|
||||
private var jammered: Boolean = false
|
||||
private var cloaked: Boolean = false
|
||||
private var flying: Boolean = false
|
||||
private var ntuCapacitor: Int = 0
|
||||
private var capacitor: Int = 0
|
||||
|
||||
/**
|
||||
* Permissions control who gets to access different parts of the vehicle;
|
||||
* the groups are Driver (seat), Gunner (seats), Passenger (seats), and the Trunk
|
||||
*/
|
||||
private val groupPermissions : Array[VehicleLockState.Value] = Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
|
||||
private var seats : Map[Int, Seat] = Map.empty
|
||||
private var cargoHolds : Map[Int, Cargo] = Map.empty
|
||||
private var weapons : Map[Int, EquipmentSlot] = Map.empty
|
||||
private var utilities : Map[Int, Utility] = Map()
|
||||
private val trunk : GridInventory = GridInventory()
|
||||
private val groupPermissions: Array[VehicleLockState.Value] =
|
||||
Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
|
||||
private var seats: Map[Int, Seat] = Map.empty
|
||||
private var cargoHolds: Map[Int, Cargo] = Map.empty
|
||||
private var weapons: Map[Int, EquipmentSlot] = Map.empty
|
||||
private var utilities: Map[Int, Utility] = Map()
|
||||
private val trunk: GridInventory = GridInventory()
|
||||
|
||||
/**
|
||||
* Records the GUID of the cargo vehicle (galaxy/lodestar) this vehicle is stored in for DismountVehicleCargoMsg use
|
||||
* DismountVehicleCargoMsg only passes the player_guid and this vehicle's guid
|
||||
*/
|
||||
private var mountedIn : Option[PlanetSideGUID] = None
|
||||
private var mountedIn: Option[PlanetSideGUID] = None
|
||||
|
||||
private var vehicleGatingManifest : Option[VehicleManifest] = None
|
||||
private var previousVehicleGatingManifest : Option[VehicleManifest] = None
|
||||
private var vehicleGatingManifest: Option[VehicleManifest] = None
|
||||
private var previousVehicleGatingManifest: Option[VehicleManifest] = None
|
||||
|
||||
//init
|
||||
LoadDefinition()
|
||||
|
|
@ -113,15 +116,15 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* Override this method to perform any special setup that is not standardized to `*Definition`.
|
||||
* @see `Vehicle.LoadDefinition`
|
||||
*/
|
||||
protected def LoadDefinition() : Unit = {
|
||||
protected def LoadDefinition(): Unit = {
|
||||
Vehicle.LoadDefinition(this)
|
||||
}
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = {
|
||||
def Faction: PlanetSideEmpire.Value = {
|
||||
this.faction
|
||||
}
|
||||
|
||||
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
override def Faction_=(faction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
|
||||
this.faction = faction
|
||||
faction
|
||||
}
|
||||
|
|
@ -129,13 +132,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
/** How long it takes to jack the vehicle in seconds, based on the hacker's certification level */
|
||||
def JackingDuration: Array[Int] = Definition.JackingDuration
|
||||
|
||||
def MountedIn : Option[PlanetSideGUID] = {
|
||||
def MountedIn: Option[PlanetSideGUID] = {
|
||||
this.mountedIn
|
||||
}
|
||||
|
||||
def MountedIn_=(cargo_vehicle_guid : PlanetSideGUID) : Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
|
||||
def MountedIn_=(cargo_vehicle_guid: PlanetSideGUID): Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
|
||||
|
||||
def MountedIn_=(cargo_vehicle_guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def MountedIn_=(cargo_vehicle_guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
cargo_vehicle_guid match {
|
||||
case Some(_) =>
|
||||
this.mountedIn = cargo_vehicle_guid
|
||||
|
|
@ -145,61 +148,61 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
MountedIn
|
||||
}
|
||||
|
||||
override def Health_=(assignHealth : Int) : Int = {
|
||||
override def Health_=(assignHealth: Int): Int = {
|
||||
//TODO should vehicle class enforce this?
|
||||
if(!Destroyed) {
|
||||
if (!Destroyed) {
|
||||
super.Health_=(assignHealth)
|
||||
}
|
||||
Health
|
||||
}
|
||||
|
||||
def Shields : Int = {
|
||||
def Shields: Int = {
|
||||
shields
|
||||
}
|
||||
|
||||
def Shields_=(strength : Int) : Int = {
|
||||
def Shields_=(strength: Int): Int = {
|
||||
shields = math.min(math.max(0, strength), MaxShields)
|
||||
Shields
|
||||
}
|
||||
|
||||
def MaxShields : Int = {
|
||||
def MaxShields: Int = {
|
||||
Definition.MaxShields
|
||||
}
|
||||
|
||||
def Decal : Int = {
|
||||
def Decal: Int = {
|
||||
decal
|
||||
}
|
||||
|
||||
def Decal_=(logo : Int) : Int = {
|
||||
def Decal_=(logo: Int): Int = {
|
||||
decal = logo
|
||||
Decal
|
||||
}
|
||||
|
||||
def Jammered : Boolean = jammered
|
||||
def Jammered: Boolean = jammered
|
||||
|
||||
def Jammered_=(jamState : Boolean) : Boolean = {
|
||||
def Jammered_=(jamState: Boolean): Boolean = {
|
||||
jammered = jamState
|
||||
Jammered
|
||||
}
|
||||
|
||||
def Cloaked : Boolean = cloaked
|
||||
def Cloaked: Boolean = cloaked
|
||||
|
||||
def Cloaked_=(isCloaked : Boolean) : Boolean = {
|
||||
def Cloaked_=(isCloaked: Boolean): Boolean = {
|
||||
cloaked = isCloaked
|
||||
Cloaked
|
||||
}
|
||||
|
||||
def Flying : Boolean = flying
|
||||
def Flying: Boolean = flying
|
||||
|
||||
def Flying_=(isFlying : Boolean) : Boolean = {
|
||||
def Flying_=(isFlying: Boolean): Boolean = {
|
||||
flying = isFlying
|
||||
Flying
|
||||
}
|
||||
|
||||
def NtuCapacitor : Int = ntuCapacitor
|
||||
def NtuCapacitor: Int = ntuCapacitor
|
||||
|
||||
def NtuCapacitor_=(value: Int) : Int = {
|
||||
if(value > Definition.MaxNtuCapacitor) {
|
||||
def NtuCapacitor_=(value: Int): Int = {
|
||||
if (value > Definition.MaxNtuCapacitor) {
|
||||
ntuCapacitor = Definition.MaxNtuCapacitor
|
||||
} else if (value < 0) {
|
||||
ntuCapacitor = 0
|
||||
|
|
@ -218,9 +221,9 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
}
|
||||
|
||||
def Capacitor : Int = capacitor
|
||||
|
||||
def Capacitor_=(value: Int) : Int = {
|
||||
if(value > Definition.MaxCapacitor) {
|
||||
|
||||
def Capacitor_=(value: Int): Int = {
|
||||
if (value > Definition.MaxCapacitor) {
|
||||
capacitor = Definition.MaxCapacitor
|
||||
} else if (value < 0) {
|
||||
capacitor = 0
|
||||
|
|
@ -235,18 +238,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param mountPoint an index representing the seat position / mounting point
|
||||
* @return a seat number, or `None`
|
||||
*/
|
||||
def GetSeatFromMountPoint(mountPoint : Int) : Option[Int] = {
|
||||
def GetSeatFromMountPoint(mountPoint: Int): Option[Int] = {
|
||||
Definition.MountPoints.get(mountPoint)
|
||||
}
|
||||
|
||||
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
|
||||
def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
|
||||
|
||||
/**
|
||||
* What are the access permissions for a position on this vehicle, seats or trunk?
|
||||
* @param group the group index
|
||||
* @return what sort of access permission exist for this group
|
||||
*/
|
||||
def PermissionGroup(group : Int) : Option[VehicleLockState.Value] = {
|
||||
def PermissionGroup(group: Int): Option[VehicleLockState.Value] = {
|
||||
reindexPermissionsGroup(group) match {
|
||||
case Some(index) =>
|
||||
Some(groupPermissions(index))
|
||||
|
|
@ -262,16 +265,17 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @return the new access permission for this group;
|
||||
* `None`, if the group does not exist or the level of permission was not changed
|
||||
*/
|
||||
def PermissionGroup(group : Int, level : Long) : Option[VehicleLockState.Value] = {
|
||||
def PermissionGroup(group: Int, level: Long): Option[VehicleLockState.Value] = {
|
||||
reindexPermissionsGroup(group) match {
|
||||
case Some(index) =>
|
||||
val current = groupPermissions(index)
|
||||
val next = try { VehicleLockState(level.toInt) } catch { case _ : Exception => groupPermissions(index) }
|
||||
if(current != next) {
|
||||
val next =
|
||||
try { VehicleLockState(level.toInt) }
|
||||
catch { case _: Exception => groupPermissions(index) }
|
||||
if (current != next) {
|
||||
groupPermissions(index) = next
|
||||
PermissionGroup(index)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
case None =>
|
||||
|
|
@ -285,15 +289,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param group the group index
|
||||
* @return the modified group index
|
||||
*/
|
||||
private def reindexPermissionsGroup(group : Int) : Option[Int] = if(group > 9 && group < 14) {
|
||||
Some(group - 10)
|
||||
}
|
||||
else if(group > -1 && group < 4) {
|
||||
Some(group)
|
||||
}
|
||||
else {
|
||||
None
|
||||
}
|
||||
private def reindexPermissionsGroup(group: Int): Option[Int] =
|
||||
if (group > 9 && group < 14) {
|
||||
Some(group - 10)
|
||||
} else if (group > -1 && group < 4) {
|
||||
Some(group)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the seat at the index.
|
||||
|
|
@ -301,37 +304,34 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param seatNumber an index representing the seat position / mounting point
|
||||
* @return a `Seat`, or `None`
|
||||
*/
|
||||
def Seat(seatNumber : Int) : Option[Seat] = {
|
||||
if(seatNumber >= 0 && seatNumber < this.seats.size) {
|
||||
def Seat(seatNumber: Int): Option[Seat] = {
|
||||
if (seatNumber >= 0 && seatNumber < this.seats.size) {
|
||||
this.seats.get(seatNumber)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def Seats : Map[Int, Seat] = {
|
||||
def Seats: Map[Int, Seat] = {
|
||||
seats
|
||||
}
|
||||
|
||||
def CargoHold(cargoNumber : Int) : Option[Cargo] = {
|
||||
if(cargoNumber >= 0) {
|
||||
def CargoHold(cargoNumber: Int): Option[Cargo] = {
|
||||
if (cargoNumber >= 0) {
|
||||
this.cargoHolds.get(cargoNumber)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def CargoHolds : Map[Int, Cargo] = {
|
||||
def CargoHolds: Map[Int, Cargo] = {
|
||||
cargoHolds
|
||||
}
|
||||
|
||||
def SeatPermissionGroup(seatNumber : Int) : Option[AccessPermissionGroup.Value] = {
|
||||
if(seatNumber == 0) {
|
||||
def SeatPermissionGroup(seatNumber: Int): Option[AccessPermissionGroup.Value] = {
|
||||
if (seatNumber == 0) {
|
||||
Some(AccessPermissionGroup.Driver)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Seat(seatNumber) match {
|
||||
case Some(seat) =>
|
||||
seat.ControlledWeapon match {
|
||||
|
|
@ -351,14 +351,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
}
|
||||
}
|
||||
|
||||
def Weapons : Map[Int, EquipmentSlot] = weapons
|
||||
def Weapons: Map[Int, EquipmentSlot] = weapons
|
||||
|
||||
/**
|
||||
* Get the weapon at the index.
|
||||
* @param wepNumber an index representing the seat position / mounting point
|
||||
* @return a weapon, or `None`
|
||||
*/
|
||||
def ControlledWeapon(wepNumber : Int) : Option[Equipment] = {
|
||||
def ControlledWeapon(wepNumber: Int): Option[Equipment] = {
|
||||
weapons.get(wepNumber) match {
|
||||
case Some(mount) =>
|
||||
mount.Equipment
|
||||
|
|
@ -372,45 +372,42 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param player the player
|
||||
* @return a seat number, or `None` if the `player` is not actually seated in this vehicle
|
||||
*/
|
||||
def PassengerInSeat(player : Player) : Option[Int] = recursivePassengerInSeat(seats.iterator, player)
|
||||
def PassengerInSeat(player: Player): Option[Int] = recursivePassengerInSeat(seats.iterator, player)
|
||||
|
||||
@tailrec private def recursivePassengerInSeat(iter : Iterator[(Int, Seat)], player : Player) : Option[Int] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursivePassengerInSeat(iter: Iterator[(Int, Seat)], player: Player): Option[Int] = {
|
||||
if (!iter.hasNext) {
|
||||
None
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val (seatNumber, seat) = iter.next
|
||||
if(seat.Occupant.contains(player)) {
|
||||
if (seat.Occupant.contains(player)) {
|
||||
Some(seatNumber)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
recursivePassengerInSeat(iter, player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def Utilities : Map[Int, Utility] = utilities
|
||||
def Utilities: Map[Int, Utility] = utilities
|
||||
|
||||
/**
|
||||
* Get a reference to a certain `Utility` attached to this `Vehicle`.
|
||||
* @param utilNumber the attachment number of the `Utility`
|
||||
* @return the `Utility` or `None` (if invalid)
|
||||
*/
|
||||
def Utility(utilNumber : Int) : Option[PlanetSideServerObject] = {
|
||||
if(utilNumber >= 0 && utilNumber < this.utilities.size) {
|
||||
def Utility(utilNumber: Int): Option[PlanetSideServerObject] = {
|
||||
if (utilNumber >= 0 && utilNumber < this.utilities.size) {
|
||||
this.utilities.get(utilNumber) match {
|
||||
case Some(util) =>
|
||||
Some(util())
|
||||
case None =>
|
||||
None
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
def Utility(utilType : UtilityType.Value) : Option[PlanetSideServerObject] = {
|
||||
def Utility(utilType: UtilityType.Value): Option[PlanetSideServerObject] = {
|
||||
utilities.values.find(_.UtilType == utilType) match {
|
||||
case Some(util) =>
|
||||
Some(util())
|
||||
|
|
@ -423,35 +420,37 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
|
||||
override def UndeployTime = Definition.UndeployTime
|
||||
|
||||
def Inventory : GridInventory = trunk
|
||||
def Inventory: GridInventory = trunk
|
||||
|
||||
def VisibleSlots : Set[Int] = weapons.keySet
|
||||
def VisibleSlots: Set[Int] = weapons.keySet
|
||||
|
||||
override def Slot(slotNum : Int) : EquipmentSlot = {
|
||||
weapons.get(slotNum)
|
||||
// .orElse(utilities.get(slotNum) match {
|
||||
// case Some(_) =>
|
||||
// //TODO what do now?
|
||||
// None
|
||||
// case None => ;
|
||||
// None
|
||||
// })
|
||||
.orElse(Some(Inventory.Slot(slotNum))).get
|
||||
override def Slot(slotNum: Int): EquipmentSlot = {
|
||||
weapons
|
||||
.get(slotNum)
|
||||
// .orElse(utilities.get(slotNum) match {
|
||||
// case Some(_) =>
|
||||
// //TODO what do now?
|
||||
// None
|
||||
// case None => ;
|
||||
// None
|
||||
// })
|
||||
.orElse(Some(Inventory.Slot(slotNum)))
|
||||
.get
|
||||
}
|
||||
|
||||
override def Find(guid : PlanetSideGUID) : Option[Int] = {
|
||||
weapons.find({ case (_, obj) =>
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
if(item.HasGUID && item.GUID == guid) {
|
||||
true
|
||||
}
|
||||
else {
|
||||
override def Find(guid: PlanetSideGUID): Option[Int] = {
|
||||
weapons.find({
|
||||
case (_, obj) =>
|
||||
obj.Equipment match {
|
||||
case Some(item) =>
|
||||
if (item.HasGUID && item.GUID == guid) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
case None =>
|
||||
false
|
||||
}
|
||||
case None =>
|
||||
false
|
||||
}
|
||||
}
|
||||
}) match {
|
||||
case Some((index, _)) =>
|
||||
Some(index)
|
||||
|
|
@ -460,7 +459,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
}
|
||||
}
|
||||
|
||||
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = {
|
||||
override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
|
||||
weapons.get(dest) match {
|
||||
case Some(slot) =>
|
||||
slot.Equipment match {
|
||||
|
|
@ -478,13 +477,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* A reference to the `Vehicle` `Trunk` space.
|
||||
* @return this `Vehicle` `Trunk`
|
||||
*/
|
||||
def Trunk : GridInventory = {
|
||||
def Trunk: GridInventory = {
|
||||
this.trunk
|
||||
}
|
||||
|
||||
def AccessingTrunk : Option[PlanetSideGUID] = trunkAccess
|
||||
def AccessingTrunk: Option[PlanetSideGUID] = trunkAccess
|
||||
|
||||
def AccessingTrunk_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = {
|
||||
def AccessingTrunk_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
|
||||
AccessingTrunk = Some(guid)
|
||||
}
|
||||
|
||||
|
|
@ -494,12 +493,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param guid the player who wishes to access the trunk
|
||||
* @return the player who is currently allowed to access the trunk
|
||||
*/
|
||||
def AccessingTrunk_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def AccessingTrunk_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
guid match {
|
||||
case None =>
|
||||
trunkAccess = None
|
||||
case Some(player) =>
|
||||
if(trunkAccess.isEmpty) {
|
||||
if (trunkAccess.isEmpty) {
|
||||
trunkAccess = Some(player)
|
||||
}
|
||||
}
|
||||
|
|
@ -511,8 +510,8 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* @param player a player attempting to access this `Trunk`
|
||||
* @return `true`, if the `player` is permitted access; `false`, otherwise
|
||||
*/
|
||||
def CanAccessTrunk(player : Player) : Boolean = {
|
||||
if(trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
|
||||
def CanAccessTrunk(player: Player): Boolean = {
|
||||
if (trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
|
||||
groupPermissions(3) match {
|
||||
case VehicleLockState.Locked => //only the owner
|
||||
Owner.isEmpty || (Owner.isDefined && player.GUID == Owner.get)
|
||||
|
|
@ -521,8 +520,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
case VehicleLockState.Empire => //anyone of the owner's faction
|
||||
faction == player.Faction
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -531,18 +529,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* Check access to the `Trunk`.
|
||||
* @return the current access value for the `Vehicle` `Trunk`
|
||||
*/
|
||||
def TrunkLockState : VehicleLockState.Value = groupPermissions(3)
|
||||
def TrunkLockState: VehicleLockState.Value = groupPermissions(3)
|
||||
|
||||
/**
|
||||
* Trunk locations are stored as the orientation zero point being to the East. We need to convert that to a North = 0 orientation before returning the location
|
||||
* @return A Vector3 of the current trunk location, orientated with North as the zero point
|
||||
*/
|
||||
def TrunkLocation : Vector3 = {
|
||||
def TrunkLocation: Vector3 = {
|
||||
val rotationRadians = -math.toRadians(Orientation.z - 90f).toFloat
|
||||
Vector3.PlanarRotateAroundPoint(Position + Definition.TrunkLocation, Position, rotationRadians)
|
||||
}
|
||||
|
||||
def PrepareGatingManifest() : VehicleManifest = {
|
||||
def PrepareGatingManifest(): VehicleManifest = {
|
||||
val manifest = VehicleManifest(this)
|
||||
seats.collect { case (index, seat) if index > 0 => seat.Occupant = None }
|
||||
vehicleGatingManifest = Some(manifest)
|
||||
|
|
@ -550,14 +548,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
manifest
|
||||
}
|
||||
|
||||
def PublishGatingManifest() : Option[VehicleManifest] = {
|
||||
def PublishGatingManifest(): Option[VehicleManifest] = {
|
||||
val out = vehicleGatingManifest
|
||||
previousVehicleGatingManifest = vehicleGatingManifest
|
||||
vehicleGatingManifest = None
|
||||
out
|
||||
}
|
||||
|
||||
def PreviousGatingManifest() : Option[VehicleManifest] = previousVehicleGatingManifest
|
||||
def PreviousGatingManifest(): Option[VehicleManifest] = previousVehicleGatingManifest
|
||||
|
||||
def DamageModel = Definition.asInstanceOf[DamageResistanceModel]
|
||||
|
||||
|
|
@ -565,30 +563,32 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
|
|||
* This is the definition entry that is used to store and unload pertinent information about the `Vehicle`.
|
||||
* @return the vehicle's definition entry
|
||||
*/
|
||||
def Definition : VehicleDefinition = vehicleDef
|
||||
def Definition: VehicleDefinition = vehicleDef
|
||||
|
||||
def canEqual(other: Any): Boolean = other.isInstanceOf[Vehicle]
|
||||
|
||||
override def equals(other : Any) : Boolean = other match {
|
||||
case that: Vehicle =>
|
||||
(that canEqual this) &&
|
||||
hashCode() == that.hashCode()
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
override def equals(other: Any): Boolean =
|
||||
other match {
|
||||
case that: Vehicle =>
|
||||
(that canEqual this) &&
|
||||
hashCode() == that.hashCode()
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
||||
override def hashCode() : Int = Actor.hashCode()
|
||||
override def hashCode(): Int = Actor.hashCode()
|
||||
|
||||
/**
|
||||
* Override the string representation to provide additional information.
|
||||
* @return the string output
|
||||
*/
|
||||
override def toString : String = {
|
||||
override def toString: String = {
|
||||
Vehicle.toString(this)
|
||||
}
|
||||
}
|
||||
|
||||
object Vehicle {
|
||||
|
||||
/**
|
||||
* A basic `Trait` connecting all of the actionable `Vehicle` response messages.
|
||||
*/
|
||||
|
|
@ -599,7 +599,7 @@ object Vehicle {
|
|||
* @param player the player who sent this request message
|
||||
* @param response the result of the processed request
|
||||
*/
|
||||
final case class VehicleMessages(player : Player, response : Exchange)
|
||||
final case class VehicleMessages(player: Player, response: Exchange)
|
||||
|
||||
/**
|
||||
* Initiate vehicle deconstruction.
|
||||
|
|
@ -607,7 +607,7 @@ object Vehicle {
|
|||
* @param time the delay before deconstruction should initiate;
|
||||
* should initiate instantly when `None`
|
||||
*/
|
||||
final case class Deconstruct(time : Option[FiniteDuration] = None)
|
||||
final case class Deconstruct(time: Option[FiniteDuration] = None)
|
||||
|
||||
/**
|
||||
* The `Vehicle` will resume previous unresponsiveness to player activity.
|
||||
|
|
@ -620,23 +620,23 @@ object Vehicle {
|
|||
* @see `FacilityBenefitShieldChargeRequestMessage`
|
||||
* @param amount the number of points to charge
|
||||
*/
|
||||
final case class ChargeShields(amount : Int)
|
||||
final case class ChargeShields(amount: Int)
|
||||
|
||||
/**
|
||||
* Following a successful shield charge tick, display the results of the update.
|
||||
* @see `FacilityBenefitShieldChargeRequestMessage`
|
||||
* @param vehicle the updated vehicle
|
||||
*/
|
||||
final case class UpdateShieldsCharge(vehicle : Vehicle)
|
||||
final case class UpdateShieldsCharge(vehicle: Vehicle)
|
||||
|
||||
/**
|
||||
* Change a vehicle's internal ownership property to match that of the target player.
|
||||
* @param player the person who will own the vehicle, or `None` if the vehicle will go unowned
|
||||
*/
|
||||
final case class Ownership(player : Option[Player])
|
||||
final case class Ownership(player: Option[Player])
|
||||
|
||||
object Ownership {
|
||||
def apply(player : Player) : Ownership = Ownership(Some(player))
|
||||
def apply(player: Player): Ownership = Ownership(Some(player))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -644,7 +644,7 @@ object Vehicle {
|
|||
* @param vehicleDef the vehicle's definition entry
|
||||
* @return a `Vehicle` object
|
||||
*/
|
||||
def apply(vehicleDef : VehicleDefinition) : Vehicle = {
|
||||
def apply(vehicleDef: VehicleDefinition): Vehicle = {
|
||||
new Vehicle(vehicleDef)
|
||||
}
|
||||
|
||||
|
|
@ -652,8 +652,8 @@ object Vehicle {
|
|||
* Given a `Map` of `Utility` objects, only return the objects with a positive or zero-index position.
|
||||
* @return a map of applicable utilities
|
||||
*/
|
||||
def EquipmentUtilities(utilities : Map[Int, Utility]) : Map[Int, Utility] = {
|
||||
utilities.filter({ case(index : Int, _ : Utility) => index > -1 })
|
||||
def EquipmentUtilities(utilities: Map[Int, Utility]): Map[Int, Utility] = {
|
||||
utilities.filter({ case (index: Int, _: Utility) => index > -1 })
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -661,30 +661,35 @@ object Vehicle {
|
|||
* @param vehicle the `Vehicle` being initialized
|
||||
* @see `{object}.LoadDefinition`
|
||||
*/
|
||||
def LoadDefinition(vehicle : Vehicle) : Vehicle = {
|
||||
val vdef : VehicleDefinition = vehicle.Definition
|
||||
def LoadDefinition(vehicle: Vehicle): Vehicle = {
|
||||
val vdef: VehicleDefinition = vehicle.Definition
|
||||
//general stuff
|
||||
vehicle.Health = vdef.DefaultHealth
|
||||
//create weapons
|
||||
vehicle.weapons = vdef.Weapons.map({case (num, definition) =>
|
||||
val slot = EquipmentSlot(EquipmentSize.VehicleWeapon)
|
||||
slot.Equipment = Tool(definition)
|
||||
num -> slot
|
||||
}).toMap
|
||||
vehicle.weapons = vdef.Weapons
|
||||
.map({
|
||||
case (num, definition) =>
|
||||
val slot = EquipmentSlot(EquipmentSize.VehicleWeapon)
|
||||
slot.Equipment = Tool(definition)
|
||||
num -> slot
|
||||
})
|
||||
.toMap
|
||||
//create seats
|
||||
vehicle.seats = vdef.Seats.map({ case(num, definition) => num -> Seat(definition)}).toMap
|
||||
vehicle.seats = vdef.Seats.map({ case (num, definition) => num -> Seat(definition) }).toMap
|
||||
// create cargo holds
|
||||
vehicle.cargoHolds = vdef.Cargo.map({ case(num, definition) => num -> Cargo(definition)}).toMap
|
||||
vehicle.cargoHolds = vdef.Cargo.map({ case (num, definition) => num -> Cargo(definition) }).toMap
|
||||
|
||||
//create utilities
|
||||
vehicle.utilities = vdef.Utilities.map({
|
||||
case(num, util) =>
|
||||
val obj = Utility(util, vehicle)
|
||||
val utilObj = obj()
|
||||
vehicle.Amenities = utilObj
|
||||
utilObj.LocationOffset = vdef.UtilityOffset.get(num)
|
||||
num -> obj
|
||||
}).toMap
|
||||
vehicle.utilities = vdef.Utilities
|
||||
.map({
|
||||
case (num, util) =>
|
||||
val obj = Utility(util, vehicle)
|
||||
val utilObj = obj()
|
||||
vehicle.Amenities = utilObj
|
||||
utilObj.LocationOffset = vdef.UtilityOffset.get(num)
|
||||
num -> obj
|
||||
})
|
||||
.toMap
|
||||
//trunk
|
||||
vdef.TrunkSize match {
|
||||
case InventoryTile.None => ;
|
||||
|
|
@ -699,7 +704,7 @@ object Vehicle {
|
|||
* Provide a fixed string representation.
|
||||
* @return the string output
|
||||
*/
|
||||
def toString(obj : Vehicle) : String = {
|
||||
def toString(obj: Vehicle): String = {
|
||||
val occupancy = obj.Seats.values.count(seat => seat.isOccupied)
|
||||
s"${obj.Definition.Name}, owned by ${obj.Owner}: (${obj.Health}/${obj.MaxHealth})(${obj.Shields}/${obj.MaxShields}) ($occupancy)"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ object Vehicles {
|
|||
* @param player na
|
||||
* @return na
|
||||
*/
|
||||
def Own(vehicle : Vehicle, player : Player) : Option[Vehicle] = Own(vehicle, Some(player))
|
||||
def Own(vehicle: Vehicle, player: Player): Option[Vehicle] = Own(vehicle, Some(player))
|
||||
|
||||
/**
|
||||
* na
|
||||
|
|
@ -28,12 +28,15 @@ object Vehicles {
|
|||
* @param playerOpt na
|
||||
* @return na
|
||||
*/
|
||||
def Own(vehicle : Vehicle, playerOpt : Option[Player]) : Option[Vehicle] = {
|
||||
def Own(vehicle: Vehicle, playerOpt: Option[Player]): Option[Vehicle] = {
|
||||
playerOpt match {
|
||||
case Some(tplayer) =>
|
||||
tplayer.VehicleOwned = vehicle.GUID
|
||||
vehicle.AssignOwnership(playerOpt)
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(vehicle.Zone.Id, VehicleAction.Ownership(tplayer.GUID, vehicle.GUID))
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
vehicle.Zone.Id,
|
||||
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
|
||||
)
|
||||
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Name)
|
||||
Some(vehicle)
|
||||
case None =>
|
||||
|
|
@ -48,26 +51,31 @@ object Vehicles {
|
|||
* @return the vehicle, if it had a previous owner;
|
||||
* `None`, otherwise
|
||||
*/
|
||||
def Disown(guid : PlanetSideGUID, vehicle : Vehicle) : Option[Vehicle] = vehicle.Zone.GUID(vehicle.Owner) match {
|
||||
case Some(player : Player) =>
|
||||
if(player.VehicleOwned.contains(guid)) {
|
||||
player.VehicleOwned = None
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(player.GUID, PlanetSideGUID(0)))
|
||||
}
|
||||
vehicle.AssignOwnership(None)
|
||||
val empire = VehicleLockState.Empire.id
|
||||
val factionChannel = s"${vehicle.Faction}"
|
||||
(0 to 2).foreach(group => {
|
||||
vehicle.PermissionGroup(group, empire)
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(factionChannel,
|
||||
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
|
||||
)
|
||||
})
|
||||
ReloadAccessPermissions(vehicle, player.Name)
|
||||
Some(vehicle)
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
def Disown(guid: PlanetSideGUID, vehicle: Vehicle): Option[Vehicle] =
|
||||
vehicle.Zone.GUID(vehicle.Owner) match {
|
||||
case Some(player: Player) =>
|
||||
if (player.VehicleOwned.contains(guid)) {
|
||||
player.VehicleOwned = None
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
player.Name,
|
||||
VehicleAction.Ownership(player.GUID, PlanetSideGUID(0))
|
||||
)
|
||||
}
|
||||
vehicle.AssignOwnership(None)
|
||||
val empire = VehicleLockState.Empire.id
|
||||
val factionChannel = s"${vehicle.Faction}"
|
||||
(0 to 2).foreach(group => {
|
||||
vehicle.PermissionGroup(group, empire)
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
factionChannel,
|
||||
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
|
||||
)
|
||||
})
|
||||
ReloadAccessPermissions(vehicle, player.Name)
|
||||
Some(vehicle)
|
||||
case _ =>
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* Disassociate a player from a vehicle that he owns.
|
||||
|
|
@ -76,7 +84,8 @@ object Vehicles {
|
|||
* This is the player side of vehicle ownership removal.
|
||||
* @param player the player
|
||||
*/
|
||||
def Disown(player : Player, zone : Zone) : Option[Vehicle] = Disown(player, Some(zone))
|
||||
def Disown(player: Player, zone: Zone): Option[Vehicle] = Disown(player, Some(zone))
|
||||
|
||||
/**
|
||||
* Disassociate a player from a vehicle that he owns.
|
||||
* The vehicle must exist in the game world on the specified continent.
|
||||
|
|
@ -84,12 +93,12 @@ object Vehicles {
|
|||
* This is the player side of vehicle ownership removal.
|
||||
* @param player the player
|
||||
*/
|
||||
def Disown(player : Player, zoneOpt : Option[Zone]) : Option[Vehicle] = {
|
||||
def Disown(player: Player, zoneOpt: Option[Zone]): Option[Vehicle] = {
|
||||
player.VehicleOwned match {
|
||||
case Some(vehicle_guid) =>
|
||||
player.VehicleOwned = None
|
||||
zoneOpt.getOrElse(player.Zone).GUID(vehicle_guid) match {
|
||||
case Some(vehicle : Vehicle) =>
|
||||
case Some(vehicle: Vehicle) =>
|
||||
Disown(player, vehicle)
|
||||
case _ =>
|
||||
None
|
||||
|
|
@ -106,21 +115,23 @@ object Vehicles {
|
|||
* This is the vehicle side of vehicle ownership removal.
|
||||
* @param player the player
|
||||
*/
|
||||
def Disown(player : Player, vehicle : Vehicle) : Option[Vehicle] = {
|
||||
def Disown(player: Player, vehicle: Vehicle): Option[Vehicle] = {
|
||||
val pguid = player.GUID
|
||||
if(vehicle.Owner.contains(pguid)) {
|
||||
if (vehicle.Owner.contains(pguid)) {
|
||||
vehicle.AssignOwnership(None)
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(pguid, PlanetSideGUID(0)))
|
||||
val vguid = vehicle.GUID
|
||||
val vguid = vehicle.GUID
|
||||
val empire = VehicleLockState.Empire.id
|
||||
(0 to 2).foreach(group => {
|
||||
vehicle.PermissionGroup(group, empire)
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(s"${vehicle.Faction}", VehicleAction.SeatPermissions(pguid, vguid, group, empire))
|
||||
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
|
||||
s"${vehicle.Faction}",
|
||||
VehicleAction.SeatPermissions(pguid, vguid, group, empire)
|
||||
)
|
||||
})
|
||||
ReloadAccessPermissions(vehicle, player.Name)
|
||||
Some(vehicle)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +145,7 @@ object Vehicles {
|
|||
* The most important examples include either the player or the vehicle itself spawning in for the first time.
|
||||
* @param vehicle the `Vehicle`
|
||||
*/
|
||||
def ReloadAccessPermissions(vehicle : Vehicle, toChannel : String) : Unit = {
|
||||
def ReloadAccessPermissions(vehicle: Vehicle, toChannel: String): Unit = {
|
||||
val vehicle_guid = vehicle.GUID
|
||||
(0 to 3).foreach(group => {
|
||||
vehicle.Zone.AvatarEvents ! AvatarServiceMessage(
|
||||
|
|
@ -170,16 +181,16 @@ object Vehicles {
|
|||
* @return `true`, if all passengers of the vehicle, and its cargo vehicles, etc., have reported being in the same zone;
|
||||
* `false`, if no manifest entry exists, or if the vehicle is moving to the same zone
|
||||
*/
|
||||
def AllGatedOccupantsInSameZone(vehicle : Vehicle) : Boolean = {
|
||||
def AllGatedOccupantsInSameZone(vehicle: Vehicle): Boolean = {
|
||||
val vzone = vehicle.Zone
|
||||
vehicle.PreviousGatingManifest() match {
|
||||
case Some(manifest) if vzone != manifest.origin =>
|
||||
val manifestPassengers = manifest.passengers.collect { case (name, _) => name } :+ manifest.driverName
|
||||
val manifestPassengers = manifest.passengers.collect { case (name, _) => name } :+ manifest.driverName
|
||||
val manifestPassengerResults = manifestPassengers.map { name => vzone.Players.exists(_.name.equals(name)) }
|
||||
manifestPassengerResults.forall(_ == true) &&
|
||||
vehicle.CargoHolds.values
|
||||
.collect { case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.Occupant.get) }
|
||||
.forall(_ == true)
|
||||
vehicle.CargoHolds.values
|
||||
.collect { case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.Occupant.get) }
|
||||
.forall(_ == true)
|
||||
case _ =>
|
||||
false
|
||||
}
|
||||
|
|
@ -192,11 +203,10 @@ object Vehicles {
|
|||
* @return the orientation as an `Integer` value;
|
||||
* `0` for almost all cases
|
||||
*/
|
||||
def CargoOrientation(vehicle : Vehicle) : Int = {
|
||||
if(vehicle.Definition == GlobalDefinitions.router) {
|
||||
def CargoOrientation(vehicle: Vehicle): Int = {
|
||||
if (vehicle.Definition == GlobalDefinitions.router) {
|
||||
1
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
@ -208,17 +218,22 @@ object Vehicles {
|
|||
* @param hacker the one whoi performed the hack and will inherit ownership of the target vehicle
|
||||
* @param unk na; used by `HackMessage` as `unk5`
|
||||
*/
|
||||
def FinishHackingVehicle(target : Vehicle, hacker : Player, unk : Long)(): Unit = {
|
||||
def FinishHackingVehicle(target: Vehicle, hacker: Player, unk: Long)(): Unit = {
|
||||
log.info(s"Vehicle guid: ${target.GUID} has been jacked")
|
||||
import scala.concurrent.duration._
|
||||
val zone = target.Zone
|
||||
// Forcefully dismount any cargo
|
||||
target.CargoHolds.values.foreach(cargoHold => {
|
||||
target.CargoHolds.values.foreach(cargoHold => {
|
||||
cargoHold.Occupant match {
|
||||
case Some(cargo : Vehicle) => {
|
||||
case Some(cargo: Vehicle) => {
|
||||
cargo.Seats(0).Occupant match {
|
||||
case Some(cargoDriver: Player) =>
|
||||
CargoBehavior.HandleVehicleCargoDismount(target.Zone, cargo.GUID, bailed = target.Flying, requestedByPassenger = false, kicked = true )
|
||||
CargoBehavior.HandleVehicleCargoDismount(
|
||||
target.Zone,
|
||||
cargo.GUID,
|
||||
bailed = target.Flying,
|
||||
requestedByPassenger = false,
|
||||
kicked = true
|
||||
)
|
||||
case None =>
|
||||
log.error("FinishHackingVehicle: vehicle in cargo hold missing driver")
|
||||
CargoBehavior.HandleVehicleCargoDismount(cargo.GUID, cargo, target.GUID, target, false, false, true)
|
||||
|
|
@ -233,20 +248,23 @@ object Vehicles {
|
|||
case Some(tplayer) =>
|
||||
seat.Occupant = None
|
||||
tplayer.VehicleSeated = None
|
||||
if(tplayer.HasGUID) {
|
||||
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID))
|
||||
if (tplayer.HasGUID) {
|
||||
zone.VehicleEvents ! VehicleServiceMessage(
|
||||
zone.Id,
|
||||
VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID)
|
||||
)
|
||||
}
|
||||
case None => ;
|
||||
}
|
||||
})
|
||||
// If the vehicle can fly and is flying deconstruct it, and well played to whomever managed to hack a plane in mid air. I'm impressed.
|
||||
if(target.Definition.CanFly && target.Flying) {
|
||||
if (target.Definition.CanFly && target.Flying) {
|
||||
// todo: Should this force the vehicle to land in the same way as when a pilot bails with passengers on board?
|
||||
target.Actor ! Vehicle.Deconstruct()
|
||||
} else { // Otherwise handle ownership transfer as normal
|
||||
// Remove ownership of our current vehicle, if we have one
|
||||
hacker.VehicleOwned match {
|
||||
case Some(guid : PlanetSideGUID) =>
|
||||
case Some(guid: PlanetSideGUID) =>
|
||||
zone.GUID(guid) match {
|
||||
case Some(vehicle: Vehicle) =>
|
||||
Vehicles.Disown(hacker, vehicle)
|
||||
|
|
@ -270,9 +288,15 @@ object Vehicles {
|
|||
Vehicles.Own(target, hacker)
|
||||
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
|
||||
// And broadcast the faction change to other clients
|
||||
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction))
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.Id,
|
||||
AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction)
|
||||
)
|
||||
}
|
||||
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f))
|
||||
zone.LocalEvents ! LocalServiceMessage(
|
||||
zone.Id,
|
||||
LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
|
||||
)
|
||||
// Clean up after specific vehicles, e.g. remove router telepads
|
||||
// If AMS is deployed, swap it to the new faction
|
||||
target.Definition match {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ package net.psforever.objects.avatar
|
|||
* #121 is the most important.
|
||||
*/
|
||||
object Avatars extends Enumeration {
|
||||
final val avatar = Value(121)
|
||||
final val avatar_bot = Value(122)
|
||||
final val avatar_bot_agile = Value(123)
|
||||
final val avatar_bot_agile_no_weapon = Value(124)
|
||||
final val avatar_bot_max = Value(125)
|
||||
final val avatar_bot_max_no_weapon = Value(126)
|
||||
final val avatar_bot_reinforced = Value(127)
|
||||
final val avatar = Value(121)
|
||||
final val avatar_bot = Value(122)
|
||||
final val avatar_bot_agile = Value(123)
|
||||
final val avatar_bot_agile_no_weapon = Value(124)
|
||||
final val avatar_bot_max = Value(125)
|
||||
final val avatar_bot_max_no_weapon = Value(126)
|
||||
final val avatar_bot_reinforced = Value(127)
|
||||
final val avatar_bot_reinforced_no_weapon = Value(128)
|
||||
final val avatar_bot_standard = Value(129)
|
||||
final val avatar_bot_standard_no_weapon = Value(130)
|
||||
final val avatar_bot_standard = Value(129)
|
||||
final val avatar_bot_standard_no_weapon = Value(130)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ import scala.collection.mutable
|
|||
|
||||
object Certification {
|
||||
object Dependencies {
|
||||
|
||||
/**
|
||||
* Find the certifications that are immediately dependent on the target certification.
|
||||
* (For `A`, find all `B` that are `B ⇒ A`.)
|
||||
* @param certification the target certification
|
||||
* @return all connected certifications
|
||||
*/
|
||||
def From(certification : CertificationType.Value) : Set[CertificationType.Value] = dependencies(certification).toSet
|
||||
def From(certification: CertificationType.Value): Set[CertificationType.Value] = dependencies(certification).toSet
|
||||
|
||||
/**
|
||||
* Find all certifications that are dependent on the target certification.
|
||||
|
|
@ -21,14 +22,13 @@ object Certification {
|
|||
* @param certification the target certification
|
||||
* @return all connected certifications
|
||||
*/
|
||||
def FromAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||
var available : List[CertificationType.Value] = List(certification)
|
||||
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||
def FromAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
|
||||
var available: List[CertificationType.Value] = List(certification)
|
||||
var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||
do {
|
||||
available = available.flatMap(cert => dependencies(cert))
|
||||
allocated ++= available
|
||||
}
|
||||
while(available.nonEmpty)
|
||||
} while (available.nonEmpty)
|
||||
allocated.toSet
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ object Certification {
|
|||
* @param certification the target certification
|
||||
* @return all connected certifications
|
||||
*/
|
||||
def For(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||
def For(certification: CertificationType.Value): Set[CertificationType.Value] = {
|
||||
(for {
|
||||
(cert, certs) <- dependencies
|
||||
if certs contains certification
|
||||
|
|
@ -51,16 +51,15 @@ object Certification {
|
|||
* @param certification the target certification
|
||||
* @return all connected certifications
|
||||
*/
|
||||
def ForAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
|
||||
var available : List[CertificationType.Value] = List(certification)
|
||||
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||
def ForAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
|
||||
var available: List[CertificationType.Value] = List(certification)
|
||||
var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
|
||||
do {
|
||||
available = available.flatMap {
|
||||
For
|
||||
}
|
||||
allocated ++= available
|
||||
}
|
||||
while(available.nonEmpty)
|
||||
} while (available.nonEmpty)
|
||||
allocated.toSet
|
||||
}
|
||||
|
||||
|
|
@ -72,83 +71,80 @@ object Certification {
|
|||
* @param certification the target certification
|
||||
* @return all connected certifications
|
||||
*/
|
||||
def Like(certification : CertificationType.Value) : Set[CertificationType.Value] = certification match {
|
||||
case AssaultBuggy =>
|
||||
Set(Harasser)
|
||||
case LightScout =>
|
||||
Set(AirCavalryScout, AssaultBuggy, Harasser)
|
||||
case UniMAX =>
|
||||
Set(AAMAX, AIMAX, AVMAX)
|
||||
case AdvancedEngineering =>
|
||||
Set(AssaultEngineering, FortificationEngineering)
|
||||
case ElectronicsExpert =>
|
||||
Set(DataCorruption, ExpertHacking)
|
||||
case _ =>
|
||||
Set.empty[CertificationType.Value]
|
||||
}
|
||||
def Like(certification: CertificationType.Value): Set[CertificationType.Value] =
|
||||
certification match {
|
||||
case AssaultBuggy =>
|
||||
Set(Harasser)
|
||||
case LightScout =>
|
||||
Set(AirCavalryScout, AssaultBuggy, Harasser)
|
||||
case UniMAX =>
|
||||
Set(AAMAX, AIMAX, AVMAX)
|
||||
case AdvancedEngineering =>
|
||||
Set(AssaultEngineering, FortificationEngineering)
|
||||
case ElectronicsExpert =>
|
||||
Set(DataCorruption, ExpertHacking)
|
||||
case _ =>
|
||||
Set.empty[CertificationType.Value]
|
||||
}
|
||||
|
||||
private val dependencies : Map[CertificationType.Value, List[CertificationType.Value]] = Map(
|
||||
StandardAssault -> List(),
|
||||
AgileExoSuit -> List(),
|
||||
ReinforcedExoSuit -> List(),
|
||||
InfiltrationSuit -> List(Phantasm),
|
||||
AIMAX -> List(),
|
||||
AVMAX -> List(),
|
||||
AAMAX -> List(),
|
||||
UniMAX -> List(),
|
||||
|
||||
StandardAssault -> List(),
|
||||
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
|
||||
AntiVehicular -> List(),
|
||||
HeavyAssault -> List(),
|
||||
Sniping -> List(),
|
||||
SpecialAssault -> List(EliteAssault),
|
||||
EliteAssault -> List(),
|
||||
|
||||
ATV -> List(Switchblade),
|
||||
Switchblade -> List(),
|
||||
Harasser -> List(),
|
||||
AssaultBuggy -> List(),
|
||||
LightScout -> List(AirCavalryAssault),
|
||||
GroundSupport -> List(),
|
||||
GroundTransport -> List(),
|
||||
ArmoredAssault1 -> List(ArmoredAssault2),
|
||||
ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
|
||||
Flail -> List(),
|
||||
|
||||
AirCavalryScout -> List(AirCavalryAssault),
|
||||
AirCavalryAssault -> List(AirCavalryInterceptor),
|
||||
AirCavalryInterceptor -> List(),
|
||||
AirSupport -> List(GalaxyGunship),
|
||||
GalaxyGunship -> List(),
|
||||
Phantasm -> List(),
|
||||
|
||||
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
|
||||
BFRAntiInfantry -> List(),
|
||||
BFRAntiAircraft -> List(),
|
||||
|
||||
Medical -> List(AdvancedMedical),
|
||||
AdvancedMedical -> List(),
|
||||
Engineering -> List(CombatEngineering),
|
||||
CombatEngineering -> List(AdvancedEngineering, AssaultEngineering, FortificationEngineering),
|
||||
AdvancedEngineering -> List(),
|
||||
AssaultEngineering -> List(),
|
||||
private val dependencies: Map[CertificationType.Value, List[CertificationType.Value]] = Map(
|
||||
StandardAssault -> List(),
|
||||
AgileExoSuit -> List(),
|
||||
ReinforcedExoSuit -> List(),
|
||||
InfiltrationSuit -> List(Phantasm),
|
||||
AIMAX -> List(),
|
||||
AVMAX -> List(),
|
||||
AAMAX -> List(),
|
||||
UniMAX -> List(),
|
||||
StandardAssault -> List(),
|
||||
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
|
||||
AntiVehicular -> List(),
|
||||
HeavyAssault -> List(),
|
||||
Sniping -> List(),
|
||||
SpecialAssault -> List(EliteAssault),
|
||||
EliteAssault -> List(),
|
||||
ATV -> List(Switchblade),
|
||||
Switchblade -> List(),
|
||||
Harasser -> List(),
|
||||
AssaultBuggy -> List(),
|
||||
LightScout -> List(AirCavalryAssault),
|
||||
GroundSupport -> List(),
|
||||
GroundTransport -> List(),
|
||||
ArmoredAssault1 -> List(ArmoredAssault2),
|
||||
ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
|
||||
Flail -> List(),
|
||||
AirCavalryScout -> List(AirCavalryAssault),
|
||||
AirCavalryAssault -> List(AirCavalryInterceptor),
|
||||
AirCavalryInterceptor -> List(),
|
||||
AirSupport -> List(GalaxyGunship),
|
||||
GalaxyGunship -> List(),
|
||||
Phantasm -> List(),
|
||||
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
|
||||
BFRAntiInfantry -> List(),
|
||||
BFRAntiAircraft -> List(),
|
||||
Medical -> List(AdvancedMedical),
|
||||
AdvancedMedical -> List(),
|
||||
Engineering -> List(CombatEngineering),
|
||||
CombatEngineering -> List(AdvancedEngineering, AssaultEngineering, FortificationEngineering),
|
||||
AdvancedEngineering -> List(),
|
||||
AssaultEngineering -> List(),
|
||||
FortificationEngineering -> List(),
|
||||
Hacking -> List(AdvancedHacking),
|
||||
AdvancedHacking -> List(DataCorruption, ElectronicsExpert, ExpertHacking),
|
||||
DataCorruption -> List(),
|
||||
ElectronicsExpert -> List(),
|
||||
ExpertHacking -> List()
|
||||
Hacking -> List(AdvancedHacking),
|
||||
AdvancedHacking -> List(DataCorruption, ElectronicsExpert, ExpertHacking),
|
||||
DataCorruption -> List(),
|
||||
ElectronicsExpert -> List(),
|
||||
ExpertHacking -> List()
|
||||
)
|
||||
}
|
||||
|
||||
object Cost {
|
||||
|
||||
/**
|
||||
* For a certification, get its point cost.
|
||||
* @param certification the certification
|
||||
* @return the cost
|
||||
*/
|
||||
def Of(certification : CertificationType.Value) : Int = points(certification)
|
||||
def Of(certification: CertificationType.Value): Int = points(certification)
|
||||
|
||||
/**
|
||||
* For a list of certifications, find the point cost of all unique certifications.
|
||||
|
|
@ -156,7 +152,7 @@ object Certification {
|
|||
* @param certifications the certification list
|
||||
* @return the total cost
|
||||
*/
|
||||
def Of(certifications : List[CertificationType.Value]) : Int = Of(certifications.toSet)
|
||||
def Of(certifications: List[CertificationType.Value]): Int = Of(certifications.toSet)
|
||||
|
||||
/**
|
||||
* For a set of certifications, find the point cost of all certifications.
|
||||
|
|
@ -164,70 +160,65 @@ object Certification {
|
|||
* @param certifications the certification list
|
||||
* @return the total cost
|
||||
*/
|
||||
def Of(certifications : Set[CertificationType.Value]) : Int = OfAll(certifications.toList)
|
||||
def Of(certifications: Set[CertificationType.Value]): Int = OfAll(certifications.toList)
|
||||
|
||||
/**
|
||||
* For a list of certifications, find the point cost of all certifications, counting any duplicates.
|
||||
* @param certifications the certification list
|
||||
* @return the total cost
|
||||
*/
|
||||
def OfAll(certifications : List[CertificationType.Value]) : Int = {
|
||||
def OfAll(certifications: List[CertificationType.Value]): Int = {
|
||||
certifications map points sum
|
||||
}
|
||||
|
||||
import CertificationType._
|
||||
private val points : Map[CertificationType.Value, Int] = Map(
|
||||
StandardExoSuit -> 0,
|
||||
AgileExoSuit -> 0,
|
||||
ReinforcedExoSuit -> 3,
|
||||
InfiltrationSuit -> 2,
|
||||
AAMAX -> 2,
|
||||
AIMAX -> 3,
|
||||
AVMAX -> 3,
|
||||
UniMAX -> 6,
|
||||
|
||||
StandardAssault -> 0,
|
||||
MediumAssault -> 2,
|
||||
AntiVehicular -> 3,
|
||||
HeavyAssault -> 4,
|
||||
Sniping -> 3,
|
||||
SpecialAssault -> 3,
|
||||
EliteAssault -> 1,
|
||||
|
||||
ATV -> 1,
|
||||
Switchblade -> 1,
|
||||
Harasser -> 1,
|
||||
AssaultBuggy -> 3,
|
||||
LightScout -> 5,
|
||||
GroundSupport -> 2,
|
||||
GroundTransport -> 2,
|
||||
ArmoredAssault1 -> 2,
|
||||
ArmoredAssault2 -> 3,
|
||||
Flail -> 1,
|
||||
|
||||
AirCavalryScout -> 3,
|
||||
AirCavalryAssault -> 2,
|
||||
AirCavalryInterceptor -> 2,
|
||||
AirSupport -> 3,
|
||||
GalaxyGunship -> 2,
|
||||
Phantasm -> 3,
|
||||
|
||||
BattleFrameRobotics -> 4,
|
||||
BFRAntiInfantry -> 1,
|
||||
BFRAntiAircraft -> 1,
|
||||
|
||||
Medical -> 3,
|
||||
AdvancedMedical -> 2,
|
||||
Engineering -> 3,
|
||||
CombatEngineering -> 2,
|
||||
AdvancedEngineering -> 5,
|
||||
AssaultEngineering -> 3,
|
||||
private val points: Map[CertificationType.Value, Int] = Map(
|
||||
StandardExoSuit -> 0,
|
||||
AgileExoSuit -> 0,
|
||||
ReinforcedExoSuit -> 3,
|
||||
InfiltrationSuit -> 2,
|
||||
AAMAX -> 2,
|
||||
AIMAX -> 3,
|
||||
AVMAX -> 3,
|
||||
UniMAX -> 6,
|
||||
StandardAssault -> 0,
|
||||
MediumAssault -> 2,
|
||||
AntiVehicular -> 3,
|
||||
HeavyAssault -> 4,
|
||||
Sniping -> 3,
|
||||
SpecialAssault -> 3,
|
||||
EliteAssault -> 1,
|
||||
ATV -> 1,
|
||||
Switchblade -> 1,
|
||||
Harasser -> 1,
|
||||
AssaultBuggy -> 3,
|
||||
LightScout -> 5,
|
||||
GroundSupport -> 2,
|
||||
GroundTransport -> 2,
|
||||
ArmoredAssault1 -> 2,
|
||||
ArmoredAssault2 -> 3,
|
||||
Flail -> 1,
|
||||
AirCavalryScout -> 3,
|
||||
AirCavalryAssault -> 2,
|
||||
AirCavalryInterceptor -> 2,
|
||||
AirSupport -> 3,
|
||||
GalaxyGunship -> 2,
|
||||
Phantasm -> 3,
|
||||
BattleFrameRobotics -> 4,
|
||||
BFRAntiInfantry -> 1,
|
||||
BFRAntiAircraft -> 1,
|
||||
Medical -> 3,
|
||||
AdvancedMedical -> 2,
|
||||
Engineering -> 3,
|
||||
CombatEngineering -> 2,
|
||||
AdvancedEngineering -> 5,
|
||||
AssaultEngineering -> 3,
|
||||
FortificationEngineering -> 3,
|
||||
Hacking -> 3,
|
||||
AdvancedHacking -> 2,
|
||||
DataCorruption -> 3,
|
||||
ElectronicsExpert -> 4,
|
||||
ExpertHacking -> 2
|
||||
Hacking -> 3,
|
||||
AdvancedHacking -> 2,
|
||||
DataCorruption -> 3,
|
||||
ElectronicsExpert -> 4,
|
||||
ExpertHacking -> 2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ import net.psforever.types.{PlanetSideEmpire, Vector3}
|
|||
import services.Service
|
||||
import services.avatar.{AvatarAction, AvatarServiceMessage}
|
||||
|
||||
class CorpseControl(player : Player) extends Actor
|
||||
with ContainableBehavior {
|
||||
class CorpseControl(player: Player) extends Actor with ContainableBehavior {
|
||||
def ContainerObject = player
|
||||
|
||||
//private [this] val log = org.log4s.getLogger(player.Name)
|
||||
|
||||
def receive : Receive = containerBehavior.orElse { case _ => ; }
|
||||
def receive: Receive = containerBehavior.orElse { case _ => ; }
|
||||
|
||||
def MessageDeferredCallback(msg : Any) : Unit = {
|
||||
def MessageDeferredCallback(msg: Any): Unit = {
|
||||
msg match {
|
||||
case Containable.MoveItem(_, item, _) =>
|
||||
//momentarily put item back where it was originally
|
||||
|
|
@ -36,18 +35,18 @@ class CorpseControl(player : Player) extends Actor
|
|||
}
|
||||
}
|
||||
|
||||
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = {
|
||||
val obj = ContainerObject
|
||||
val zone = obj.Zone
|
||||
def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
|
||||
val obj = ContainerObject
|
||||
val zone = obj.Zone
|
||||
val events = zone.AvatarEvents
|
||||
item.Faction = PlanetSideEmpire.NEUTRAL
|
||||
events ! AvatarServiceMessage(zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
|
||||
}
|
||||
|
||||
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = {
|
||||
val obj = ContainerObject
|
||||
val zone = obj.Zone
|
||||
val events = zone.AvatarEvents
|
||||
def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
|
||||
val obj = ContainerObject
|
||||
val zone = obj.Zone
|
||||
val events = zone.AvatarEvents
|
||||
val definition = item.Definition
|
||||
events ! AvatarServiceMessage(
|
||||
zone.Id,
|
||||
|
|
@ -63,10 +62,11 @@ class CorpseControl(player : Player) extends Actor
|
|||
)
|
||||
}
|
||||
|
||||
def SwapItemCallback(item : Equipment) : Unit = {
|
||||
val obj = ContainerObject
|
||||
def SwapItemCallback(item: Equipment): Unit = {
|
||||
val obj = ContainerObject
|
||||
val zone = obj.Zone
|
||||
zone.AvatarEvents ! AvatarServiceMessage(zone.Id,
|
||||
zone.AvatarEvents ! AvatarServiceMessage(
|
||||
zone.Id,
|
||||
AvatarAction.SendResponse(
|
||||
Service.defaultPlayerGUID,
|
||||
ObjectDetachMessage(obj.GUID, item.GUID, Vector3.Zero, 0f)
|
||||
|
|
|
|||
|
|
@ -23,29 +23,36 @@ import scala.collection.mutable
|
|||
* these structures are updated to reflect proper count.
|
||||
*/
|
||||
class DeployableToolbox {
|
||||
|
||||
/**
|
||||
* a map of bins for keeping track of the quantities of deployables in a category
|
||||
* keys: categories, values: quantity storage object
|
||||
*/
|
||||
private val categoryCounts = DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
||||
private val categoryCounts =
|
||||
DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
||||
categoryCounts(DeployableCategory.Telepads).Max = 1024
|
||||
|
||||
/**
|
||||
* a map of bins for keeping track of the quantities of individual deployables
|
||||
* keys: deployable types, values: quantity storage object
|
||||
*/
|
||||
private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
|
||||
deployableCounts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||
|
||||
/**
|
||||
* a map of tracked/owned individual deployables
|
||||
* keys: categories, values: deployable objects
|
||||
*/
|
||||
private val deployableLists =
|
||||
DeployableCategory.values.toSeq.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() }).toMap
|
||||
DeployableCategory.values.toSeq
|
||||
.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() })
|
||||
.toMap
|
||||
|
||||
/**
|
||||
* can only be initialized once
|
||||
* set during the `Initialization` method primarily, and in `Add` and in `Remove` if not
|
||||
*/
|
||||
private var initialized : Boolean = false
|
||||
private var initialized: Boolean = false
|
||||
|
||||
/**
|
||||
* Set up the initial deployable counts by providing certification values to be used in category and unit selection.
|
||||
|
|
@ -53,13 +60,12 @@ class DeployableToolbox {
|
|||
* @return `true`, if this is the first time and actual "initialization" is performed;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Initialize(certifications : Set[CertificationType.Value]) : Boolean = {
|
||||
if(!initialized) {
|
||||
def Initialize(certifications: Set[CertificationType.Value]): Boolean = {
|
||||
if (!initialized) {
|
||||
DeployableToolbox.Initialize(deployableCounts, categoryCounts, certifications)
|
||||
initialized = true
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +78,10 @@ class DeployableToolbox {
|
|||
* occasionally, important former certification values are required for additional configuration;
|
||||
* the new certification should already have been added to this group
|
||||
*/
|
||||
def AddToDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
|
||||
def AddToDeployableQuantities(
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): Unit = {
|
||||
initialized = true
|
||||
DeployableToolbox.AddToDeployableQuantities(deployableCounts, categoryCounts, certification, certificationSet)
|
||||
}
|
||||
|
|
@ -86,7 +95,10 @@ class DeployableToolbox {
|
|||
* occasionally, important former certification values are required for additional configuration;
|
||||
* the new certification should already have been excluded from this group
|
||||
*/
|
||||
def RemoveFromDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
|
||||
def RemoveFromDeployableQuantities(
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): Unit = {
|
||||
initialized = true
|
||||
DeployableToolbox.RemoveFromDeployablesQuantities(deployableCounts, categoryCounts, certification, certificationSet)
|
||||
}
|
||||
|
|
@ -100,7 +112,7 @@ class DeployableToolbox {
|
|||
* @return `true`, if it can be managed under the current conditions;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Accept(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
def Accept(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
Valid(obj) && Available(obj) && !Contains(obj)
|
||||
}
|
||||
|
||||
|
|
@ -111,9 +123,9 @@ class DeployableToolbox {
|
|||
* @return `true`, if both category maximum and deployable type maximum are positive non-zero integers;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Valid(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
def Valid(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Max > 0 &&
|
||||
categoryCounts(obj.Definition.DeployCategory).Max > 0
|
||||
categoryCounts(obj.Definition.DeployCategory).Max > 0
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -124,9 +136,9 @@ class DeployableToolbox {
|
|||
* @return `true`, if the deployable can be added to the support lists and counted;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Available(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available &&
|
||||
categoryCounts(obj.Definition.DeployCategory).Available
|
||||
def Available(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available &&
|
||||
categoryCounts(obj.Definition.DeployCategory).Available
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,7 +148,7 @@ class DeployableToolbox {
|
|||
* @return `true`, if the deployable can be found in one of the lists;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Contains(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
def Contains(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
deployableLists(obj.Definition.DeployCategory).contains(obj)
|
||||
}
|
||||
|
||||
|
|
@ -152,18 +164,17 @@ class DeployableToolbox {
|
|||
* @return `true`, if the deployable is added;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Add(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
val category = obj.Definition.DeployCategory
|
||||
def Add(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
val category = obj.Definition.DeployCategory
|
||||
val dCategory = categoryCounts(category)
|
||||
val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item))
|
||||
val dList = deployableLists(category)
|
||||
if(dCategory.Available() && dType.Available() && !dList.contains(obj)) {
|
||||
val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item))
|
||||
val dList = deployableLists(category)
|
||||
if (dCategory.Available() && dType.Available() && !dList.contains(obj)) {
|
||||
dCategory.Current += 1
|
||||
dType.Current += 1
|
||||
dList += obj
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -179,16 +190,15 @@ class DeployableToolbox {
|
|||
* @return `true`, if the deployable is added;
|
||||
* `false`, otherwise
|
||||
*/
|
||||
def Remove(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
|
||||
val category = obj.Definition.DeployCategory
|
||||
def Remove(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
|
||||
val category = obj.Definition.DeployCategory
|
||||
val deployables = deployableLists(category)
|
||||
if(deployables.contains(obj)) {
|
||||
if (deployables.contains(obj)) {
|
||||
categoryCounts(category).Current -= 1
|
||||
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Current -= 1
|
||||
deployables -= obj
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -199,7 +209,7 @@ class DeployableToolbox {
|
|||
* @param obj the example deployable
|
||||
* @return any deployable that is found
|
||||
*/
|
||||
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable) : Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
def DisplaceFirst(obj: DeployableToolbox.AcceptableDeployable): Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
DisplaceFirst(obj, { d => d.Definition.Item == obj.Definition.Item })
|
||||
}
|
||||
|
||||
|
|
@ -213,11 +223,14 @@ class DeployableToolbox {
|
|||
* @param rule the testing rule for determining a valid deployable
|
||||
* @return any deployable that is found
|
||||
*/
|
||||
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable, rule : (Deployable)=> Boolean) : Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
val definition = obj.Definition
|
||||
val category = definition.DeployCategory
|
||||
def DisplaceFirst(
|
||||
obj: DeployableToolbox.AcceptableDeployable,
|
||||
rule: (Deployable) => Boolean
|
||||
): Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
val definition = obj.Definition
|
||||
val category = definition.DeployCategory
|
||||
val categoryList = deployableLists(category)
|
||||
if(categoryList.nonEmpty) {
|
||||
if (categoryList.nonEmpty) {
|
||||
val found = categoryList.find(rule) match {
|
||||
case Some(target) =>
|
||||
categoryList.remove(categoryList.indexOf(target))
|
||||
|
|
@ -227,8 +240,7 @@ class DeployableToolbox {
|
|||
categoryCounts(category).Current -= 1
|
||||
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
|
||||
Some(found)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -239,15 +251,14 @@ class DeployableToolbox {
|
|||
* @param category the target category
|
||||
* @return any deployable that is found
|
||||
*/
|
||||
def DisplaceFirst(category : DeployableCategory.Value) : Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
def DisplaceFirst(category: DeployableCategory.Value): Option[DeployableToolbox.AcceptableDeployable] = {
|
||||
val categoryList = deployableLists(category)
|
||||
if(categoryList.nonEmpty) {
|
||||
if (categoryList.nonEmpty) {
|
||||
val found = categoryList.remove(0)
|
||||
categoryCounts(category).Current -= 1
|
||||
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
|
||||
Some(found)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -257,7 +268,7 @@ class DeployableToolbox {
|
|||
* @param filter the example deployable
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def Deployables(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = {
|
||||
def Deployables(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
|
||||
Deployables(filter.Definition.Item)
|
||||
}
|
||||
|
||||
|
|
@ -266,10 +277,11 @@ class DeployableToolbox {
|
|||
* @param filter the type of deployable
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def Deployables(filter : DeployedItem.Value) : List[PlanetSideGUID] = {
|
||||
def Deployables(filter: DeployedItem.Value): List[PlanetSideGUID] = {
|
||||
deployableLists(Deployable.Category.Of(filter))
|
||||
.filter(entry => { entry.Definition.Item == filter })
|
||||
.map(_.GUID).toList
|
||||
.map(_.GUID)
|
||||
.toList
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -277,7 +289,7 @@ class DeployableToolbox {
|
|||
* @param filter the example deployable
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def Category(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = {
|
||||
def Category(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
|
||||
Category(filter.Definition.DeployCategory)
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +298,7 @@ class DeployableToolbox {
|
|||
* @param filter the type of deployable
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def Category(filter : DeployableCategory.Value) : List[PlanetSideGUID] = {
|
||||
def Category(filter: DeployableCategory.Value): List[PlanetSideGUID] = {
|
||||
deployableLists(filter).map(_.GUID).toList
|
||||
}
|
||||
|
||||
|
|
@ -295,7 +307,7 @@ class DeployableToolbox {
|
|||
* @param item the example deployable
|
||||
* @return the current quantity of deployables and the maximum number
|
||||
*/
|
||||
def CountDeployable(item : DeployedItem.Value) : (Int, Int) = {
|
||||
def CountDeployable(item: DeployedItem.Value): (Int, Int) = {
|
||||
val dType = deployableCounts(DeployableToolbox.UnifiedType(item))
|
||||
(dType.Current, dType.Max)
|
||||
}
|
||||
|
|
@ -305,21 +317,21 @@ class DeployableToolbox {
|
|||
* @param item the example deployable
|
||||
* @return the current quantity of deployables and the maximum number
|
||||
*/
|
||||
def CountCategory(item : DeployedItem.Value) : (Int, Int) = {
|
||||
def CountCategory(item: DeployedItem.Value): (Int, Int) = {
|
||||
val dCat = categoryCounts(Deployable.Category.Of(DeployableToolbox.UnifiedType(item)))
|
||||
(dCat.Current, dCat.Max)
|
||||
}
|
||||
|
||||
def UpdateUIElement(entry : DeployedItem.Value) : List[(Int,Int,Int,Int)] = {
|
||||
val toEntry = DeployableToolbox.UnifiedType(entry)
|
||||
def UpdateUIElement(entry: DeployedItem.Value): List[(Int, Int, Int, Int)] = {
|
||||
val toEntry = DeployableToolbox.UnifiedType(entry)
|
||||
val (curr, max) = Deployable.UI(toEntry)
|
||||
val dType = deployableCounts(toEntry)
|
||||
val dType = deployableCounts(toEntry)
|
||||
List((curr, dType.Current, max, dType.Max))
|
||||
}
|
||||
|
||||
def UpdateUI() : List[(Int,Int,Int,Int)] = DeployedItem.values flatMap UpdateUIElement toList
|
||||
def UpdateUI(): List[(Int, Int, Int, Int)] = DeployedItem.values flatMap UpdateUIElement toList
|
||||
|
||||
def UpdateUI(entry : CertificationType.Value) : List[(Int,Int,Int,Int)] = {
|
||||
def UpdateUI(entry: CertificationType.Value): List[(Int, Int, Int, Int)] = {
|
||||
import CertificationType._
|
||||
entry match {
|
||||
case AdvancedHacking =>
|
||||
|
|
@ -327,19 +339,26 @@ class DeployableToolbox {
|
|||
|
||||
case CombatEngineering =>
|
||||
List(
|
||||
DeployedItem.boomer, DeployedItem.he_mine, DeployedItem.spitfire_turret, DeployedItem.motionalarmsensor
|
||||
DeployedItem.boomer,
|
||||
DeployedItem.he_mine,
|
||||
DeployedItem.spitfire_turret,
|
||||
DeployedItem.motionalarmsensor
|
||||
) flatMap UpdateUIElement
|
||||
|
||||
case AssaultEngineering =>
|
||||
List(
|
||||
DeployedItem.jammer_mine, DeployedItem.portable_manned_turret, DeployedItem.deployable_shield_generator
|
||||
DeployedItem.jammer_mine,
|
||||
DeployedItem.portable_manned_turret,
|
||||
DeployedItem.deployable_shield_generator
|
||||
) flatMap UpdateUIElement
|
||||
|
||||
case FortificationEngineering =>
|
||||
List(
|
||||
DeployedItem.boomer,
|
||||
DeployedItem.he_mine,
|
||||
DeployedItem.spitfire_turret, DeployedItem.spitfire_cloaked, DeployedItem.spitfire_aa,
|
||||
DeployedItem.spitfire_turret,
|
||||
DeployedItem.spitfire_cloaked,
|
||||
DeployedItem.spitfire_aa,
|
||||
DeployedItem.motionalarmsensor,
|
||||
DeployedItem.tank_traps
|
||||
) flatMap UpdateUIElement
|
||||
|
|
@ -352,7 +371,7 @@ class DeployableToolbox {
|
|||
}
|
||||
}
|
||||
|
||||
def UpdateUI(certifications : List[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
|
||||
def UpdateUI(certifications: List[CertificationType.Value]): List[(Int, Int, Int, Int)] = {
|
||||
certifications flatMap UpdateUI
|
||||
}
|
||||
|
||||
|
|
@ -361,11 +380,11 @@ class DeployableToolbox {
|
|||
* @param item the deployable type
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def ClearDeployable(item : DeployedItem.Value) : List[PlanetSideGUID] = {
|
||||
val uitem = DeployableToolbox.UnifiedType(item)
|
||||
val category = Deployable.Category.Of(uitem)
|
||||
def ClearDeployable(item: DeployedItem.Value): List[PlanetSideGUID] = {
|
||||
val uitem = DeployableToolbox.UnifiedType(item)
|
||||
val category = Deployable.Category.Of(uitem)
|
||||
val categoryList = deployableLists(category)
|
||||
val (out, in) = categoryList.partition(_.Definition.Item == item)
|
||||
val (out, in) = categoryList.partition(_.Definition.Item == item)
|
||||
|
||||
categoryList.clear()
|
||||
categoryList ++= in
|
||||
|
|
@ -379,13 +398,13 @@ class DeployableToolbox {
|
|||
* @param item the deployable type belonging to a category
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def ClearCategory(item : DeployedItem.Value) : List[PlanetSideGUID] = {
|
||||
def ClearCategory(item: DeployedItem.Value): List[PlanetSideGUID] = {
|
||||
val category = Deployable.Category.Of(DeployableToolbox.UnifiedType(item))
|
||||
val out = deployableLists(category).map(_.GUID).toList
|
||||
val out = deployableLists(category).map(_.GUID).toList
|
||||
deployableLists(category).clear()
|
||||
categoryCounts(category).Current = 0
|
||||
(Deployable.Category.Includes(category) map DeployableToolbox.UnifiedType toSet)
|
||||
.foreach({item : DeployedItem.Value => deployableCounts(item).Current = 0 })
|
||||
.foreach({ item: DeployedItem.Value => deployableCounts(item).Current = 0 })
|
||||
out
|
||||
}
|
||||
|
||||
|
|
@ -393,7 +412,7 @@ class DeployableToolbox {
|
|||
* Remove all managed deployables.
|
||||
* @return a list of globally unique identifiers that should be valid for the current zone
|
||||
*/
|
||||
def Clear() : List[PlanetSideGUID] = {
|
||||
def Clear(): List[PlanetSideGUID] = {
|
||||
val out = deployableLists.values.flatten.map(_.GUID).toList
|
||||
deployableLists.values.foreach(_.clear())
|
||||
deployableCounts.values.foreach(_.Current = 0)
|
||||
|
|
@ -403,6 +422,7 @@ class DeployableToolbox {
|
|||
}
|
||||
|
||||
object DeployableToolbox {
|
||||
|
||||
/**
|
||||
* A `type` intended to properly define the minimum acceptable conditions for a `Deployable` object.
|
||||
*/
|
||||
|
|
@ -413,26 +433,28 @@ object DeployableToolbox {
|
|||
* There are deployable numbers organized by deploybale type and by deployable category.
|
||||
*/
|
||||
private class Bin {
|
||||
|
||||
/** the maximum number of deployables for this criteria that can be managed */
|
||||
private var max : Int = 0
|
||||
private var max: Int = 0
|
||||
|
||||
/** the current number of deployables for this criteria that are being managed */
|
||||
private var current : Int = 0
|
||||
private var current: Int = 0
|
||||
|
||||
def Current : Int = current
|
||||
def Current: Int = current
|
||||
|
||||
def Current_=(curr : Int) : Int = {
|
||||
def Current_=(curr: Int): Int = {
|
||||
current = curr
|
||||
Current
|
||||
}
|
||||
|
||||
def Max : Int = max
|
||||
def Max: Int = max
|
||||
|
||||
def Max_=(mx : Int) : Int = {
|
||||
def Max_=(mx: Int): Int = {
|
||||
max = mx
|
||||
Max
|
||||
}
|
||||
|
||||
def Available() : Boolean = current < max
|
||||
def Available(): Boolean = current < max
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -441,12 +463,14 @@ object DeployableToolbox {
|
|||
* @param item the type of deployable
|
||||
* @return the corrected deployable type
|
||||
*/
|
||||
def UnifiedType(item : DeployedItem.Value) : DeployedItem.Value = item match {
|
||||
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr | DeployedItem.portable_manned_turret_vs =>
|
||||
DeployedItem.portable_manned_turret
|
||||
case _ =>
|
||||
item
|
||||
}
|
||||
def UnifiedType(item: DeployedItem.Value): DeployedItem.Value =
|
||||
item match {
|
||||
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr |
|
||||
DeployedItem.portable_manned_turret_vs =>
|
||||
DeployedItem.portable_manned_turret
|
||||
case _ =>
|
||||
item
|
||||
}
|
||||
|
||||
/**
|
||||
* Hardcoded maximum values for the category and type initialization.
|
||||
|
|
@ -454,9 +478,13 @@ object DeployableToolbox {
|
|||
* @param categories a reference to the category `Bin` object
|
||||
* @param certifications a group of certifications for the initial values
|
||||
*/
|
||||
private def Initialize(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certifications : Set[CertificationType.Value]) : Unit = {
|
||||
private def Initialize(
|
||||
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
|
||||
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
|
||||
certifications: Set[CertificationType.Value]
|
||||
): Unit = {
|
||||
import CertificationType._
|
||||
if(certifications.contains(AdvancedEngineering)) {
|
||||
if (certifications.contains(AdvancedEngineering)) {
|
||||
counts(DeployedItem.boomer).Max = 25
|
||||
counts(DeployedItem.he_mine).Max = 25
|
||||
counts(DeployedItem.jammer_mine).Max = 20
|
||||
|
|
@ -478,12 +506,11 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.FieldTurrets).Max = 1
|
||||
categories(DeployableCategory.ShieldGenerators).Max = 1
|
||||
|
||||
if(certifications.contains(AdvancedHacking)) {
|
||||
if (certifications.contains(AdvancedHacking)) {
|
||||
counts(DeployedItem.sensor_shield).Max = 25
|
||||
}
|
||||
}
|
||||
else if(certifications.contains(CombatEngineering)) {
|
||||
if(certifications.contains(AssaultEngineering)) {
|
||||
} else if (certifications.contains(CombatEngineering)) {
|
||||
if (certifications.contains(AssaultEngineering)) {
|
||||
counts(DeployedItem.jammer_mine).Max = 20
|
||||
counts(DeployedItem.portable_manned_turret).Max = 1 //the below turret types are unified
|
||||
//counts(DeployedItem.portable_manned_turret_nc).Max = 1
|
||||
|
|
@ -493,7 +520,7 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.FieldTurrets).Max = 1
|
||||
categories(DeployableCategory.ShieldGenerators).Max = 1
|
||||
}
|
||||
if(certifications.contains(FortificationEngineering)) {
|
||||
if (certifications.contains(FortificationEngineering)) {
|
||||
counts(DeployedItem.boomer).Max = 25
|
||||
counts(DeployedItem.he_mine).Max = 25
|
||||
counts(DeployedItem.spitfire_turret).Max = 15
|
||||
|
|
@ -506,8 +533,7 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.SmallTurrets).Max = 15
|
||||
categories(DeployableCategory.Sensors).Max = 25
|
||||
categories(DeployableCategory.TankTraps).Max = 5
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
counts(DeployedItem.boomer).Max = 20
|
||||
counts(DeployedItem.he_mine).Max = 20
|
||||
counts(DeployedItem.spitfire_turret).Max = 10
|
||||
|
|
@ -518,11 +544,11 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.Sensors).Max = 20
|
||||
}
|
||||
|
||||
if(certifications.contains(AdvancedHacking)) {
|
||||
if (certifications.contains(AdvancedHacking)) {
|
||||
counts(DeployedItem.sensor_shield).Max = 20
|
||||
}
|
||||
}
|
||||
if(certifications.contains(CertificationType.GroundSupport)) {
|
||||
if (certifications.contains(CertificationType.GroundSupport)) {
|
||||
counts(DeployedItem.router_telepad_deployable).Max = 1024
|
||||
categories(DeployableCategory.Telepads).Max = 1024
|
||||
}
|
||||
|
|
@ -535,12 +561,17 @@ object DeployableToolbox {
|
|||
* @param certification the new certification
|
||||
* @param certificationSet the group of previous certifications being tracked
|
||||
*/
|
||||
def AddToDeployableQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
|
||||
def AddToDeployableQuantities(
|
||||
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
|
||||
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): Unit = {
|
||||
import CertificationType._
|
||||
if(certificationSet contains certification) {
|
||||
if (certificationSet contains certification) {
|
||||
certification match {
|
||||
case AdvancedHacking =>
|
||||
if(certificationSet contains CombatEngineering) {
|
||||
if (certificationSet contains CombatEngineering) {
|
||||
counts(DeployedItem.sensor_shield).Max = 20
|
||||
}
|
||||
|
||||
|
|
@ -553,7 +584,7 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.Mines).Max = 20
|
||||
categories(DeployableCategory.SmallTurrets).Max = 10
|
||||
categories(DeployableCategory.Sensors).Max = 20
|
||||
if(certificationSet contains AdvancedHacking) {
|
||||
if (certificationSet contains AdvancedHacking) {
|
||||
counts(DeployedItem.sensor_shield).Max = 20
|
||||
}
|
||||
|
||||
|
|
@ -582,11 +613,21 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.TankTraps).Max = 5
|
||||
|
||||
case AdvancedEngineering =>
|
||||
if(!certificationSet.contains(AssaultEngineering)) {
|
||||
AddToDeployableQuantities(counts, categories, AssaultEngineering, certificationSet ++ Set(AssaultEngineering))
|
||||
if (!certificationSet.contains(AssaultEngineering)) {
|
||||
AddToDeployableQuantities(
|
||||
counts,
|
||||
categories,
|
||||
AssaultEngineering,
|
||||
certificationSet ++ Set(AssaultEngineering)
|
||||
)
|
||||
}
|
||||
if(!certificationSet.contains(FortificationEngineering)) {
|
||||
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering))
|
||||
if (!certificationSet.contains(FortificationEngineering)) {
|
||||
AddToDeployableQuantities(
|
||||
counts,
|
||||
categories,
|
||||
FortificationEngineering,
|
||||
certificationSet ++ Set(FortificationEngineering)
|
||||
)
|
||||
}
|
||||
|
||||
// case GroundSupport =>
|
||||
|
|
@ -605,9 +646,14 @@ object DeployableToolbox {
|
|||
* @param certification the new certification
|
||||
* @param certificationSet the group of previous certifications being tracked
|
||||
*/
|
||||
def RemoveFromDeployablesQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
|
||||
def RemoveFromDeployablesQuantities(
|
||||
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
|
||||
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
|
||||
certification: CertificationType.Value,
|
||||
certificationSet: Set[CertificationType.Value]
|
||||
): Unit = {
|
||||
import CertificationType._
|
||||
if(!certificationSet.contains(certification)) {
|
||||
if (!certificationSet.contains(certification)) {
|
||||
certification match {
|
||||
case AdvancedHacking =>
|
||||
counts(DeployedItem.sensor_shield).Max = 0
|
||||
|
|
@ -625,17 +671,17 @@ object DeployableToolbox {
|
|||
|
||||
case AssaultEngineering =>
|
||||
counts(DeployedItem.jammer_mine).Max = 0
|
||||
counts(DeployedItem.portable_manned_turret).Max = 0 //the below turret types are unified
|
||||
counts(DeployedItem.portable_manned_turret).Max = 0 //the below turret types are unified
|
||||
//counts(DeployedItem.portable_manned_turret_nc).Max = 0
|
||||
//counts(DeployedItem.portable_manned_turret_tr).Max = 0
|
||||
//counts(DeployedItem.portable_manned_turret_vs).Max = 0
|
||||
counts(DeployedItem.deployable_shield_generator).Max = 0
|
||||
categories(DeployableCategory.Sensors).Max = if(certificationSet contains CombatEngineering) 20 else 0
|
||||
categories(DeployableCategory.Sensors).Max = if (certificationSet contains CombatEngineering) 20 else 0
|
||||
categories(DeployableCategory.FieldTurrets).Max = 0
|
||||
categories(DeployableCategory.ShieldGenerators).Max = 0
|
||||
|
||||
case FortificationEngineering =>
|
||||
val ce : Int = if(certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0
|
||||
val ce: Int = if (certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0
|
||||
counts(DeployedItem.boomer).Max = ce * 20
|
||||
counts(DeployedItem.he_mine).Max = ce * 20
|
||||
counts(DeployedItem.spitfire_turret).Max = ce * 10
|
||||
|
|
@ -650,10 +696,10 @@ object DeployableToolbox {
|
|||
categories(DeployableCategory.TankTraps).Max = 0
|
||||
|
||||
case AdvancedEngineering =>
|
||||
if(!certificationSet.contains(AssaultEngineering)) {
|
||||
if (!certificationSet.contains(AssaultEngineering)) {
|
||||
RemoveFromDeployablesQuantities(counts, categories, AssaultEngineering, certificationSet)
|
||||
}
|
||||
if(!certificationSet.contains(FortificationEngineering)) {
|
||||
if (!certificationSet.contains(FortificationEngineering)) {
|
||||
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@ package net.psforever.objects.avatar
|
|||
|
||||
object FirstTimeEvents {
|
||||
object TR {
|
||||
val InfantryWeapons : Set[String] = Set(
|
||||
"used_chainblade","used_repeater","used_cycler","used_mini_chaingun","used_striker",
|
||||
val InfantryWeapons: Set[String] = Set(
|
||||
"used_chainblade",
|
||||
"used_repeater",
|
||||
"used_cycler",
|
||||
"used_mini_chaingun",
|
||||
"used_striker",
|
||||
"used_anniversary_guna"
|
||||
)
|
||||
|
||||
val Vehicles : Set[String] = Set(
|
||||
val Vehicles: Set[String] = Set(
|
||||
"used_heavy_grenade_launcher",
|
||||
"used_apc_tr_weapon",
|
||||
"used_15mm_chaingun",
|
||||
|
|
@ -18,27 +22,38 @@ object FirstTimeEvents {
|
|||
"used_colossus_cluster_bomb_pod",
|
||||
"used_colossus_dual_100mm_cannons",
|
||||
"used_colossus_tank_cannon",
|
||||
"visited_threemanheavybuggy","visited_battlewagon","visited_apc_tr","visited_prowler",
|
||||
"visited_colossus_flight","visited_colossus_gunner"
|
||||
"visited_threemanheavybuggy",
|
||||
"visited_battlewagon",
|
||||
"visited_apc_tr",
|
||||
"visited_prowler",
|
||||
"visited_colossus_flight",
|
||||
"visited_colossus_gunner"
|
||||
)
|
||||
|
||||
val Other : Set[String] = Set(
|
||||
"used_trhev_dualcycler","used_trhev_pounder","used_trhev_burster",
|
||||
"used_colossus_dual_100mm_cannons","used_colossus_tank_cannon",
|
||||
val Other: Set[String] = Set(
|
||||
"used_trhev_dualcycler",
|
||||
"used_trhev_pounder",
|
||||
"used_trhev_burster",
|
||||
"used_colossus_dual_100mm_cannons",
|
||||
"used_colossus_tank_cannon",
|
||||
"used_energy_gun_tr",
|
||||
"visited_portable_manned_turret_tr"
|
||||
)
|
||||
|
||||
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
|
||||
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
}
|
||||
|
||||
object NC {
|
||||
val InfantryWeapons : Set[String] = Set(
|
||||
"used_magcutter","used_isp","used_gauss","used_r_shotgun","used_hunterseeker",
|
||||
val InfantryWeapons: Set[String] = Set(
|
||||
"used_magcutter",
|
||||
"used_isp",
|
||||
"used_gauss",
|
||||
"used_r_shotgun",
|
||||
"used_hunterseeker",
|
||||
"used_anniversary_gun"
|
||||
)
|
||||
|
||||
val Vehicles : Set[String] = Set(
|
||||
val Vehicles: Set[String] = Set(
|
||||
"used_firebird",
|
||||
"used_gauss_cannon",
|
||||
"used_apc_nc_weapon",
|
||||
|
|
@ -48,26 +63,36 @@ object FirstTimeEvents {
|
|||
"used_peregrine_mechhammer",
|
||||
"used_peregrine_particle_cannon",
|
||||
"used_peregrine_sparrow",
|
||||
"visited_twomanheavybuggy","visited_thunderer","visited_apc_nc","visited_vanguard",
|
||||
"visited_peregrine_flight","visited_peregrine_gunner"
|
||||
"visited_twomanheavybuggy",
|
||||
"visited_thunderer",
|
||||
"visited_apc_nc",
|
||||
"visited_vanguard",
|
||||
"visited_peregrine_flight",
|
||||
"visited_peregrine_gunner"
|
||||
)
|
||||
|
||||
val Other : Set[String] = Set(
|
||||
"used_nchev_scattercannon","used_nchev_falcon","used_nchev_sparrow",
|
||||
val Other: Set[String] = Set(
|
||||
"used_nchev_scattercannon",
|
||||
"used_nchev_falcon",
|
||||
"used_nchev_sparrow",
|
||||
"used_energy_gun_nc",
|
||||
"visited_portable_manned_turret_nc"
|
||||
)
|
||||
|
||||
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
}
|
||||
|
||||
object VS {
|
||||
val InfantryWeapons : Set[String] = Set(
|
||||
"used_forceblade","used_beamer","used_pulsar","used_lasher","used_lancer",
|
||||
val InfantryWeapons: Set[String] = Set(
|
||||
"used_forceblade",
|
||||
"used_beamer",
|
||||
"used_pulsar",
|
||||
"used_lasher",
|
||||
"used_lancer",
|
||||
"used_anniversary_gunb"
|
||||
)
|
||||
|
||||
val Vehicles : Set[String] = Set(
|
||||
val Vehicles: Set[String] = Set(
|
||||
"used_fluxpod",
|
||||
"used_apc_vs_weapon",
|
||||
"used_heavy_rail_beam",
|
||||
|
|
@ -78,27 +103,45 @@ object FirstTimeEvents {
|
|||
"used_aphelion_immolation_cannon",
|
||||
"used_aphelion_plasma_rocket_pod",
|
||||
"used_aphelion_ppa",
|
||||
"visited_twomanhoverbuggy","visited_aurora","visited_apc_vs","visited_magrider",
|
||||
"visited_aphelion_flight","visited_aphelion_gunner"
|
||||
"visited_twomanhoverbuggy",
|
||||
"visited_aurora",
|
||||
"visited_apc_vs",
|
||||
"visited_magrider",
|
||||
"visited_aphelion_flight",
|
||||
"visited_aphelion_gunner"
|
||||
)
|
||||
|
||||
val Other : Set[String] = Set(
|
||||
"used_vshev_quasar","used_vshev_comet","used_vshev_starfire",
|
||||
val Other: Set[String] = Set(
|
||||
"used_vshev_quasar",
|
||||
"used_vshev_comet",
|
||||
"used_vshev_starfire",
|
||||
"used_energy_gun_vs",
|
||||
"visited_portable_manned_turret_vs"
|
||||
)
|
||||
|
||||
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
|
||||
}
|
||||
|
||||
object Standard {
|
||||
val InfantryWeapons : Set[String] = Set(
|
||||
"used_grenade_plasma","used_grenade_jammer","used_grenade_frag",
|
||||
val InfantryWeapons: Set[String] = Set(
|
||||
"used_grenade_plasma",
|
||||
"used_grenade_jammer",
|
||||
"used_grenade_frag",
|
||||
"used_katana",
|
||||
"used_ilc9","used_suppressor","used_punisher","used_flechette","used_phoenix","used_thumper","used_rocklet","used_bolt_driver","used_heavy_sniper","used_oicw","used_flamethrower"
|
||||
"used_ilc9",
|
||||
"used_suppressor",
|
||||
"used_punisher",
|
||||
"used_flechette",
|
||||
"used_phoenix",
|
||||
"used_thumper",
|
||||
"used_rocklet",
|
||||
"used_bolt_driver",
|
||||
"used_heavy_sniper",
|
||||
"used_oicw",
|
||||
"used_flamethrower"
|
||||
)
|
||||
|
||||
val Vehicles : Set[String] = Set(
|
||||
val Vehicles: Set[String] = Set(
|
||||
"used_armor_siphon",
|
||||
"used_ntu_siphon",
|
||||
"used_ballgun",
|
||||
|
|
@ -116,50 +159,95 @@ object FirstTimeEvents {
|
|||
"used_vulture_nose_cannon",
|
||||
"used_vulture_tail_cannon",
|
||||
"used_liberator_bombardier",
|
||||
"visited_ams","visited_ant",
|
||||
"visited_quadassault","visited_fury","visited_quadstealth",
|
||||
"visited_two_man_assault_buggy","visited_skyguard",
|
||||
"visited_mediumtransport","visited_apc","visited_lightning",
|
||||
"visited_mosquito","visited_lightgunship","visited_wasp",
|
||||
"visited_liberator","visited_vulture","visited_dropship","visited_galaxy_gunship",
|
||||
"visited_phantasm","visited_lodestar"
|
||||
"visited_ams",
|
||||
"visited_ant",
|
||||
"visited_quadassault",
|
||||
"visited_fury",
|
||||
"visited_quadstealth",
|
||||
"visited_two_man_assault_buggy",
|
||||
"visited_skyguard",
|
||||
"visited_mediumtransport",
|
||||
"visited_apc",
|
||||
"visited_lightning",
|
||||
"visited_mosquito",
|
||||
"visited_lightgunship",
|
||||
"visited_wasp",
|
||||
"visited_liberator",
|
||||
"visited_vulture",
|
||||
"visited_dropship",
|
||||
"visited_galaxy_gunship",
|
||||
"visited_phantasm",
|
||||
"visited_lodestar"
|
||||
)
|
||||
|
||||
val Facilities : Set[String] = Set(
|
||||
"visited_broadcast_warpgate","visited_warpgate_small",
|
||||
"visited_respawn_terminal","visited_deconstruction_terminal",
|
||||
"visited_capture_terminal","visited_secondary_capture","visited_LLU_socket","visited_resource_silo",
|
||||
"visited_med_terminal","visited_adv_med_terminal","visited_repair_silo",
|
||||
"visited_order_terminal","visited_certification_terminal","visited_implant_terminal","visited_locker",
|
||||
"visited_ground_vehicle_terminal","visited_bfr_terminal","visited_air_vehicle_terminal","visited_galaxy_terminal",
|
||||
"visited_generator","visited_generator_terminal",
|
||||
"visited_wall_turret","used_phalanx","used_phalanx_avcombo","used_phalanx_flakcombo",
|
||||
val Facilities: Set[String] = Set(
|
||||
"visited_broadcast_warpgate",
|
||||
"visited_warpgate_small",
|
||||
"visited_respawn_terminal",
|
||||
"visited_deconstruction_terminal",
|
||||
"visited_capture_terminal",
|
||||
"visited_secondary_capture",
|
||||
"visited_LLU_socket",
|
||||
"visited_resource_silo",
|
||||
"visited_med_terminal",
|
||||
"visited_adv_med_terminal",
|
||||
"visited_repair_silo",
|
||||
"visited_order_terminal",
|
||||
"visited_certification_terminal",
|
||||
"visited_implant_terminal",
|
||||
"visited_locker",
|
||||
"visited_ground_vehicle_terminal",
|
||||
"visited_bfr_terminal",
|
||||
"visited_air_vehicle_terminal",
|
||||
"visited_galaxy_terminal",
|
||||
"visited_generator",
|
||||
"visited_generator_terminal",
|
||||
"visited_wall_turret",
|
||||
"used_phalanx",
|
||||
"used_phalanx_avcombo",
|
||||
"used_phalanx_flakcombo",
|
||||
"visited_external_door_lock"
|
||||
)
|
||||
|
||||
val Other : Set[String] = Set(
|
||||
val Other: Set[String] = Set(
|
||||
"used_command_uplink",
|
||||
"used_med_app","used_nano_dispenser","used_bank","used_ace","used_advanced_ace","used_rek","used_trek","used_laze_pointer","used_telepad",
|
||||
"visited_motion_sensor","visited_sensor_shield",
|
||||
"visited_spitfire_turret","visited_spitfire_cloaked","visited_spitfire_aa",
|
||||
"visited_shield_generator","visited_tank_traps"
|
||||
"used_med_app",
|
||||
"used_nano_dispenser",
|
||||
"used_bank",
|
||||
"used_ace",
|
||||
"used_advanced_ace",
|
||||
"used_rek",
|
||||
"used_trek",
|
||||
"used_laze_pointer",
|
||||
"used_telepad",
|
||||
"visited_motion_sensor",
|
||||
"visited_sensor_shield",
|
||||
"visited_spitfire_turret",
|
||||
"visited_spitfire_cloaked",
|
||||
"visited_spitfire_aa",
|
||||
"visited_shield_generator",
|
||||
"visited_tank_traps"
|
||||
)
|
||||
|
||||
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
|
||||
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
|
||||
}
|
||||
|
||||
object Cavern {
|
||||
val InfantryWeapons : Set[String] = Set(
|
||||
"used_spiker","used_radiator","used_maelstrom"
|
||||
val InfantryWeapons: Set[String] = Set(
|
||||
"used_spiker",
|
||||
"used_radiator",
|
||||
"used_maelstrom"
|
||||
)
|
||||
|
||||
val Vehicles : Set[String] = Set(
|
||||
val Vehicles: Set[String] = Set(
|
||||
"used_scythe",
|
||||
"used_flail_weapon",
|
||||
"visited_switchblade","visited_flail","visited_router"
|
||||
"visited_switchblade",
|
||||
"visited_flail",
|
||||
"visited_router"
|
||||
)
|
||||
|
||||
val Facilities : Set[String] = Set(
|
||||
val Facilities: Set[String] = Set(
|
||||
"used_ancient_turret_weapon",
|
||||
"visited_vanu_control_console",
|
||||
"visited_ancient_air_vehicle_terminal",
|
||||
|
|
@ -172,21 +260,43 @@ object FirstTimeEvents {
|
|||
"visited_energy_crystal"
|
||||
)
|
||||
|
||||
val Other : Set[String] = Set(
|
||||
val Other: Set[String] = Set(
|
||||
"visited_vanu_module"
|
||||
)
|
||||
|
||||
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
|
||||
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
|
||||
}
|
||||
|
||||
val Maps : Set[String] = Set(
|
||||
"map01","map02","map03","map04","map05","map06","map07","map08","map09","map10",
|
||||
"map11","map12","map13","map14","map15","map16",
|
||||
"ugd01","ugd02","ugd03","ugd04","ugd05","ugd06",
|
||||
"map96","map97","map98","map99"
|
||||
val Maps: Set[String] = Set(
|
||||
"map01",
|
||||
"map02",
|
||||
"map03",
|
||||
"map04",
|
||||
"map05",
|
||||
"map06",
|
||||
"map07",
|
||||
"map08",
|
||||
"map09",
|
||||
"map10",
|
||||
"map11",
|
||||
"map12",
|
||||
"map13",
|
||||
"map14",
|
||||
"map15",
|
||||
"map16",
|
||||
"ugd01",
|
||||
"ugd02",
|
||||
"ugd03",
|
||||
"ugd04",
|
||||
"ugd05",
|
||||
"ugd06",
|
||||
"map96",
|
||||
"map97",
|
||||
"map98",
|
||||
"map99"
|
||||
)
|
||||
|
||||
val Monoliths : Set[String] = Set(
|
||||
val Monoliths: Set[String] = Set(
|
||||
"visited_monolith_amerish",
|
||||
"visited_monolith_ceryshen",
|
||||
"visited_monolith_cyssor",
|
||||
|
|
@ -198,7 +308,7 @@ object FirstTimeEvents {
|
|||
"visited_monolith_solsar"
|
||||
)
|
||||
|
||||
val Gingerman : Set[String] = Set(
|
||||
val Gingerman: Set[String] = Set(
|
||||
"visited_gingerman_atar",
|
||||
"visited_gingerman_dahaka",
|
||||
"visited_gingerman_hvar",
|
||||
|
|
@ -211,7 +321,7 @@ object FirstTimeEvents {
|
|||
"visited_gingerman_zal"
|
||||
)
|
||||
|
||||
val Sled : Set[String] = Set(
|
||||
val Sled: Set[String] = Set(
|
||||
"visited_sled01",
|
||||
"visited_sled02",
|
||||
"visited_sled04",
|
||||
|
|
@ -222,7 +332,7 @@ object FirstTimeEvents {
|
|||
"visited_sled09"
|
||||
)
|
||||
|
||||
val Snowman : Set[String] = Set(
|
||||
val Snowman: Set[String] = Set(
|
||||
"visited_snowman_amerish",
|
||||
"visited_snowman_ceryshen",
|
||||
"visited_snowman_cyssor",
|
||||
|
|
@ -234,7 +344,7 @@ object FirstTimeEvents {
|
|||
"visited_snowman_solsar"
|
||||
)
|
||||
|
||||
val Charlie : Set[String] = Set(
|
||||
val Charlie: Set[String] = Set(
|
||||
"visited_charlie01",
|
||||
"visited_charlie02",
|
||||
"visited_charlie03",
|
||||
|
|
@ -246,22 +356,58 @@ object FirstTimeEvents {
|
|||
"visited_charlie09"
|
||||
)
|
||||
|
||||
val BattleRanks : Set[String] = Set(
|
||||
"xpe_battle_rank_1","xpe_battle_rank_2","xpe_battle_rank_3","xpe_battle_rank_4","xpe_battle_rank_5",
|
||||
"xpe_battle_rank_6","xpe_battle_rank_7","xpe_battle_rank_8","xpe_battle_rank_9","xpe_battle_rank_10",
|
||||
"xpe_battle_rank_11","xpe_battle_rank_12","xpe_battle_rank_13","xpe_battle_rank_14","xpe_battle_rank_15",
|
||||
"xpe_battle_rank_16","xpe_battle_rank_17","xpe_battle_rank_18","xpe_battle_rank_19","xpe_battle_rank_20",
|
||||
"xpe_battle_rank_21","xpe_battle_rank_22","xpe_battle_rank_23","xpe_battle_rank_24","xpe_battle_rank_25",
|
||||
"xpe_battle_rank_26","xpe_battle_rank_27","xpe_battle_rank_28","xpe_battle_rank_29","xpe_battle_rank_30",
|
||||
"xpe_battle_rank_31","xpe_battle_rank_32","xpe_battle_rank_33","xpe_battle_rank_34","xpe_battle_rank_35",
|
||||
"xpe_battle_rank_36","xpe_battle_rank_37","xpe_battle_rank_38","xpe_battle_rank_39","xpe_battle_rank_40"
|
||||
val BattleRanks: Set[String] = Set(
|
||||
"xpe_battle_rank_1",
|
||||
"xpe_battle_rank_2",
|
||||
"xpe_battle_rank_3",
|
||||
"xpe_battle_rank_4",
|
||||
"xpe_battle_rank_5",
|
||||
"xpe_battle_rank_6",
|
||||
"xpe_battle_rank_7",
|
||||
"xpe_battle_rank_8",
|
||||
"xpe_battle_rank_9",
|
||||
"xpe_battle_rank_10",
|
||||
"xpe_battle_rank_11",
|
||||
"xpe_battle_rank_12",
|
||||
"xpe_battle_rank_13",
|
||||
"xpe_battle_rank_14",
|
||||
"xpe_battle_rank_15",
|
||||
"xpe_battle_rank_16",
|
||||
"xpe_battle_rank_17",
|
||||
"xpe_battle_rank_18",
|
||||
"xpe_battle_rank_19",
|
||||
"xpe_battle_rank_20",
|
||||
"xpe_battle_rank_21",
|
||||
"xpe_battle_rank_22",
|
||||
"xpe_battle_rank_23",
|
||||
"xpe_battle_rank_24",
|
||||
"xpe_battle_rank_25",
|
||||
"xpe_battle_rank_26",
|
||||
"xpe_battle_rank_27",
|
||||
"xpe_battle_rank_28",
|
||||
"xpe_battle_rank_29",
|
||||
"xpe_battle_rank_30",
|
||||
"xpe_battle_rank_31",
|
||||
"xpe_battle_rank_32",
|
||||
"xpe_battle_rank_33",
|
||||
"xpe_battle_rank_34",
|
||||
"xpe_battle_rank_35",
|
||||
"xpe_battle_rank_36",
|
||||
"xpe_battle_rank_37",
|
||||
"xpe_battle_rank_38",
|
||||
"xpe_battle_rank_39",
|
||||
"xpe_battle_rank_40"
|
||||
)
|
||||
|
||||
val CommandRanks : Set[String] = Set(
|
||||
"xpe_command_rank_1","xpe_command_rank_2","xpe_command_rank_3","xpe_command_rank_4","xpe_command_rank_5"
|
||||
val CommandRanks: Set[String] = Set(
|
||||
"xpe_command_rank_1",
|
||||
"xpe_command_rank_2",
|
||||
"xpe_command_rank_3",
|
||||
"xpe_command_rank_4",
|
||||
"xpe_command_rank_5"
|
||||
)
|
||||
|
||||
val Training : Set[String] = Set(
|
||||
val Training: Set[String] = Set(
|
||||
"training_welcome",
|
||||
"training_map",
|
||||
"training_hart",
|
||||
|
|
@ -275,13 +421,13 @@ object FirstTimeEvents {
|
|||
"training_implants"
|
||||
)
|
||||
|
||||
val OldTraining : Set[String] = Set(
|
||||
val OldTraining: Set[String] = Set(
|
||||
"training_start_tr",
|
||||
"training_start_nc",
|
||||
"training_start_vs"
|
||||
)
|
||||
|
||||
val Generic : Set[String] = Set(
|
||||
val Generic: Set[String] = Set(
|
||||
"xpe_overhead_map",
|
||||
"xpe_mail_alert",
|
||||
"xpe_join_platoon",
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
package net.psforever.objects.avatar
|
||||
|
||||
import net.psforever.objects.loadouts.Loadout
|
||||
import net.psforever.types.LoadoutType
|
||||
|
||||
import scala.util.Success
|
||||
|
||||
class LoadoutManager(size : Int) {
|
||||
private val entries : Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None)
|
||||
class LoadoutManager(size: Int) {
|
||||
private val entries: Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None)
|
||||
|
||||
def SaveLoadout(owner : Any, label : String, line : Int) : Unit = {
|
||||
def SaveLoadout(owner: Any, label: String, line: Int): Unit = {
|
||||
Loadout.Create(owner, label) match {
|
||||
case Success(loadout) if entries.length > line =>
|
||||
entries(line) = Some(loadout)
|
||||
|
|
@ -17,13 +16,14 @@ class LoadoutManager(size : Int) {
|
|||
}
|
||||
}
|
||||
|
||||
def LoadLoadout(line : Int) : Option[Loadout] = entries.lift(line).flatten
|
||||
def LoadLoadout(line: Int): Option[Loadout] = entries.lift(line).flatten
|
||||
|
||||
def DeleteLoadout(line : Int) : Unit = {
|
||||
if(entries.length > line) {
|
||||
def DeleteLoadout(line: Int): Unit = {
|
||||
if (entries.length > line) {
|
||||
entries(line) = None
|
||||
}
|
||||
}
|
||||
|
||||
def Loadouts : Seq[(Int, Loadout)] = entries.zipWithIndex.collect { case(Some(loadout), index) => (index, loadout) } toSeq
|
||||
def Loadouts: Seq[(Int, Loadout)] =
|
||||
entries.zipWithIndex.collect { case (Some(loadout), index) => (index, loadout) } toSeq
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -7,27 +7,29 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
|
|||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
health : Int,
|
||||
shields : Int,
|
||||
ownerName : String,
|
||||
position : Vector3,
|
||||
orientation : Vector3) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def
|
||||
def Health = health
|
||||
def Shields = shields
|
||||
def OwnerName = ownerName
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = None
|
||||
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||
final case class ComplexDeployableSource(
|
||||
obj_def: ObjectDefinition with BaseDeployableDefinition,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
health: Int,
|
||||
shields: Int,
|
||||
ownerName: String,
|
||||
position: Vector3,
|
||||
orientation: Vector3
|
||||
) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
|
||||
def Health = health
|
||||
def Shields = shields
|
||||
def OwnerName = ownerName
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = None
|
||||
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||
}
|
||||
|
||||
object ComplexDeployableSource {
|
||||
def apply(obj : ComplexDeployable) : ComplexDeployableSource = {
|
||||
def apply(obj: ComplexDeployable): ComplexDeployableSource = {
|
||||
ComplexDeployableSource(
|
||||
obj.Definition,
|
||||
obj.Faction,
|
||||
|
|
@ -39,7 +41,7 @@ object ComplexDeployableSource {
|
|||
)
|
||||
}
|
||||
|
||||
def apply(obj : TurretDeployable) : ComplexDeployableSource = {
|
||||
def apply(obj: TurretDeployable): ComplexDeployableSource = {
|
||||
ComplexDeployableSource(
|
||||
obj.Definition,
|
||||
obj.Faction,
|
||||
|
|
|
|||
|
|
@ -7,25 +7,27 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
|
|||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
health : Int,
|
||||
ownerName : String,
|
||||
position : Vector3,
|
||||
orientation : Vector3) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def
|
||||
def Health = health
|
||||
def OwnerName = ownerName
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = None
|
||||
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||
final case class DeployableSource(
|
||||
obj_def: ObjectDefinition with BaseDeployableDefinition,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
health: Int,
|
||||
ownerName: String,
|
||||
position: Vector3,
|
||||
orientation: Vector3
|
||||
) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
|
||||
def Health = health
|
||||
def OwnerName = ownerName
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = None
|
||||
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
|
||||
}
|
||||
|
||||
object DeployableSource {
|
||||
def apply(obj : PlanetSideGameObject with Deployable) : DeployableSource = {
|
||||
def apply(obj: PlanetSideGameObject with Deployable): DeployableSource = {
|
||||
DeployableSource(
|
||||
obj.Definition,
|
||||
obj.Faction,
|
||||
|
|
|
|||
|
|
@ -6,22 +6,24 @@ import net.psforever.objects.serverobject.affinity.FactionAffinity
|
|||
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
final case class ObjectSource(obj : PlanetSideGameObject with FactionAffinity,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
position : Vector3,
|
||||
orientation : Vector3,
|
||||
velocity : Option[Vector3]) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
|
||||
final case class ObjectSource(
|
||||
obj: PlanetSideGameObject with FactionAffinity,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
position: Vector3,
|
||||
orientation: Vector3,
|
||||
velocity: Option[Vector3]
|
||||
) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
|
||||
override def Faction = faction
|
||||
def Definition = obj.Definition
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = new ResistanceProfileMutators { }
|
||||
def Definition = obj.Definition
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = new ResistanceProfileMutators {}
|
||||
}
|
||||
|
||||
object ObjectSource {
|
||||
def apply(obj : PlanetSideGameObject with FactionAffinity) : ObjectSource = {
|
||||
def apply(obj: PlanetSideGameObject with FactionAffinity): ObjectSource = {
|
||||
ObjectSource(
|
||||
obj,
|
||||
obj.Faction,
|
||||
|
|
|
|||
|
|
@ -6,36 +6,49 @@ import net.psforever.objects.definition.{ExoSuitDefinition, ObjectDefinition}
|
|||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||
import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3}
|
||||
|
||||
final case class PlayerSource(name : String,
|
||||
char_id : Long,
|
||||
obj_def : ObjectDefinition,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
exosuit : ExoSuitType.Value,
|
||||
seated : Boolean,
|
||||
health : Int,
|
||||
armor : Int,
|
||||
position : Vector3,
|
||||
orientation : Vector3,
|
||||
velocity : Option[Vector3],
|
||||
modifiers : ResistanceProfile) extends SourceEntry {
|
||||
override def Name = name
|
||||
final case class PlayerSource(
|
||||
name: String,
|
||||
char_id: Long,
|
||||
obj_def: ObjectDefinition,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
exosuit: ExoSuitType.Value,
|
||||
seated: Boolean,
|
||||
health: Int,
|
||||
armor: Int,
|
||||
position: Vector3,
|
||||
orientation: Vector3,
|
||||
velocity: Option[Vector3],
|
||||
modifiers: ResistanceProfile
|
||||
) extends SourceEntry {
|
||||
override def Name = name
|
||||
override def Faction = faction
|
||||
override def CharId = char_id
|
||||
def Definition = obj_def
|
||||
def ExoSuit = exosuit
|
||||
def Seated = seated
|
||||
def Health = health
|
||||
def Armor = armor
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = modifiers
|
||||
override def CharId = char_id
|
||||
def Definition = obj_def
|
||||
def ExoSuit = exosuit
|
||||
def Seated = seated
|
||||
def Health = health
|
||||
def Armor = armor
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = modifiers
|
||||
}
|
||||
|
||||
object PlayerSource {
|
||||
def apply(tplayer : Player) : PlayerSource = {
|
||||
PlayerSource(tplayer.Name, tplayer.CharId, tplayer.Definition, tplayer.Faction, tplayer.ExoSuit, tplayer.VehicleSeated.nonEmpty,
|
||||
tplayer.Health, tplayer.Armor, tplayer.Position, tplayer.Orientation, tplayer.Velocity,
|
||||
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction))
|
||||
def apply(tplayer: Player): PlayerSource = {
|
||||
PlayerSource(
|
||||
tplayer.Name,
|
||||
tplayer.CharId,
|
||||
tplayer.Definition,
|
||||
tplayer.Faction,
|
||||
tplayer.ExoSuit,
|
||||
tplayer.VehicleSeated.nonEmpty,
|
||||
tplayer.Health,
|
||||
tplayer.Armor,
|
||||
tplayer.Position,
|
||||
tplayer.Orientation,
|
||||
tplayer.Velocity,
|
||||
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,51 +28,57 @@ import net.psforever.types.Vector3
|
|||
* @param fire_time when the weapon discharged was recorded;
|
||||
* defaults to `System.nanoTime`
|
||||
*/
|
||||
final case class Projectile(profile : ProjectileDefinition,
|
||||
tool_def : ToolDefinition,
|
||||
fire_mode : FireModeDefinition,
|
||||
owner : SourceEntry,
|
||||
attribute_to : Int,
|
||||
shot_origin : Vector3,
|
||||
shot_angle : Vector3,
|
||||
fire_time: Long = System.nanoTime) extends PlanetSideGameObject {
|
||||
final case class Projectile(
|
||||
profile: ProjectileDefinition,
|
||||
tool_def: ToolDefinition,
|
||||
fire_mode: FireModeDefinition,
|
||||
owner: SourceEntry,
|
||||
attribute_to: Int,
|
||||
shot_origin: Vector3,
|
||||
shot_angle: Vector3,
|
||||
fire_time: Long = System.nanoTime
|
||||
) extends PlanetSideGameObject {
|
||||
Position = shot_origin
|
||||
Orientation = shot_angle
|
||||
Velocity = {
|
||||
val initVel : Int = profile.InitialVelocity //initial velocity
|
||||
val radAngle : Double = math.toRadians(shot_angle.y) //angle of elevation
|
||||
val rise : Float = initVel * math.sin(radAngle).toFloat //z
|
||||
val ground : Float = initVel * math.cos(radAngle).toFloat //base
|
||||
val initVel: Int = profile.InitialVelocity //initial velocity
|
||||
val radAngle: Double = math.toRadians(shot_angle.y) //angle of elevation
|
||||
val rise: Float = initVel * math.sin(radAngle).toFloat //z
|
||||
val ground: Float = initVel * math.cos(radAngle).toFloat //base
|
||||
Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise)
|
||||
}
|
||||
|
||||
/** Information about the current world coordinates and orientation of the projectile */
|
||||
val current : SimpleWorldEntity = new SimpleWorldEntity()
|
||||
private var resolved : ProjectileResolution.Value = ProjectileResolution.Unresolved
|
||||
val current: SimpleWorldEntity = new SimpleWorldEntity()
|
||||
private var resolved: ProjectileResolution.Value = ProjectileResolution.Unresolved
|
||||
|
||||
/**
|
||||
* Mark the projectile as being "encountered" or "managed" at least once.
|
||||
*/
|
||||
def Resolve() : Unit = {
|
||||
def Resolve(): Unit = {
|
||||
resolved = ProjectileResolution.Resolved
|
||||
}
|
||||
|
||||
def Miss() : Unit = {
|
||||
def Miss(): Unit = {
|
||||
resolved = ProjectileResolution.MissedShot
|
||||
}
|
||||
|
||||
def isResolved : Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot
|
||||
def isResolved: Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot
|
||||
|
||||
def isMiss : Boolean = resolved == ProjectileResolution.MissedShot
|
||||
def isMiss: Boolean = resolved == ProjectileResolution.MissedShot
|
||||
|
||||
def Definition = profile
|
||||
}
|
||||
|
||||
object Projectile {
|
||||
|
||||
/** the first projectile GUID used by all clients internally */
|
||||
final val BaseUID : Int = 40100
|
||||
final val BaseUID: Int = 40100
|
||||
|
||||
/** all clients progress through 40100 to 40124 normally, skipping only for long-lived projectiles
|
||||
* 40125 to 40149 are being reserved as a guard against undetected overflow */
|
||||
final val RangeUID : Int = 40150
|
||||
* 40125 to 40149 are being reserved as a guard against undetected overflow
|
||||
*/
|
||||
final val RangeUID: Int = 40150
|
||||
|
||||
/**
|
||||
* Overloaded constructor for an `Unresolved` projectile.
|
||||
|
|
@ -84,7 +90,14 @@ object Projectile {
|
|||
* @param shot_angle in which direction the projectile was aimed when it was discharged
|
||||
* @return the `Projectile` object
|
||||
*/
|
||||
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, shot_origin : Vector3, shot_angle : Vector3) : Projectile = {
|
||||
def apply(
|
||||
profile: ProjectileDefinition,
|
||||
tool_def: ToolDefinition,
|
||||
fire_mode: FireModeDefinition,
|
||||
owner: PlanetSideGameObject with FactionAffinity,
|
||||
shot_origin: Vector3,
|
||||
shot_angle: Vector3
|
||||
): Projectile = {
|
||||
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle)
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +112,15 @@ object Projectile {
|
|||
* @param shot_angle in which direction the projectile was aimed when it was discharged
|
||||
* @return the `Projectile` object
|
||||
*/
|
||||
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, attribute_to : Int, shot_origin : Vector3, shot_angle : Vector3) : Projectile = {
|
||||
def apply(
|
||||
profile: ProjectileDefinition,
|
||||
tool_def: ToolDefinition,
|
||||
fire_mode: FireModeDefinition,
|
||||
owner: PlanetSideGameObject with FactionAffinity,
|
||||
attribute_to: Int,
|
||||
shot_origin: Vector3,
|
||||
shot_angle: Vector3
|
||||
): Projectile = {
|
||||
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,11 @@ package net.psforever.objects.ballistics
|
|||
object ProjectileResolution extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
val
|
||||
Unresolved, //original basic non-resolution
|
||||
MissedShot, //projectile did not encounter any collision object and was despawned
|
||||
Resolved, //a general "projectile encountered something" status with a more specific resolution
|
||||
Hit, //direct hit, one target
|
||||
Splash, //area of effect damage, potentially multiple targets
|
||||
Lash //lashing damage, potentially multiple targets
|
||||
val Unresolved, //original basic non-resolution
|
||||
MissedShot, //projectile did not encounter any collision object and was despawned
|
||||
Resolved, //a general "projectile encountered something" status with a more specific resolution
|
||||
Hit, //direct hit, one target
|
||||
Splash, //area of effect damage, potentially multiple targets
|
||||
Lash //lashing damage, potentially multiple targets
|
||||
= Value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,143 +7,143 @@ package net.psforever.objects.ballistics
|
|||
object Projectiles extends Enumeration {
|
||||
final val no_projectile = Value(0)
|
||||
|
||||
final val bullet_105mm_projectile = Value(1)
|
||||
final val bullet_12mm_projectile = Value(4)
|
||||
final val bullet_12mm_projectileb = Value(5)
|
||||
final val bullet_150mm_projectile = Value(7)
|
||||
final val bullet_15mm_apc_projectile = Value(10)
|
||||
final val bullet_15mm_projectile = Value(11)
|
||||
final val bullet_20mm_apc_projectile = Value(17)
|
||||
final val bullet_20mm_projectile = Value(18)
|
||||
final val bullet_25mm_projectile = Value(20)
|
||||
final val bullet_35mm_projectile = Value(22)
|
||||
final val bullet_75mm_apc_projectile = Value(26)
|
||||
final val bullet_75mm_projectile = Value(27)
|
||||
final val bullet_9mm_AP_projectile = Value(30)
|
||||
final val bullet_9mm_projectile = Value(31)
|
||||
final val anniversary_projectilea = Value(58)
|
||||
final val anniversary_projectileb = Value(59)
|
||||
final val aphelion_immolation_cannon_projectile = Value(87)
|
||||
final val aphelion_laser_projectile = Value(91)
|
||||
final val aphelion_plasma_rocket_projectile = Value(99)
|
||||
final val aphelion_ppa_projectile = Value(103)
|
||||
final val aphelion_starfire_projectile = Value(108)
|
||||
final val bolt_projectile = Value(147)
|
||||
final val burster_projectile = Value(155)
|
||||
final val chainblade_projectile = Value(176)
|
||||
final val colossus_100mm_projectile = Value(181)
|
||||
final val colossus_burster_projectile = Value(188)
|
||||
final val colossus_chaingun_projectile = Value(193)
|
||||
final val colossus_cluster_bomb_projectile = Value(197)
|
||||
final val colossus_tank_cannon_projectile = Value(207)
|
||||
final val comet_projectile = Value(210)
|
||||
final val dualcycler_projectile = Value(266)
|
||||
final val dynomite_projectile = Value(268)
|
||||
final val energy_cell_projectile = Value(273)
|
||||
final val energy_gun_nc_projectile = Value(277)
|
||||
final val energy_gun_tr_projectile = Value(279)
|
||||
final val energy_gun_vs_projectile = Value(281)
|
||||
final val enhanced_energy_cell_projectile = Value(282)
|
||||
final val enhanced_quasar_projectile = Value(283)
|
||||
final val falcon_projectile = Value(286)
|
||||
final val firebird_missile_projectile = Value(288)
|
||||
final val flail_projectile = Value(296)
|
||||
final val flamethrower_fireball = Value(302)
|
||||
final val flamethrower_projectile = Value(303)
|
||||
final val flux_cannon_apc_projectile = Value(305)
|
||||
final val flux_cannon_thresher_projectile = Value(308)
|
||||
final val fluxpod_projectile = Value(311)
|
||||
final val forceblade_projectile = Value(325)
|
||||
final val frag_cartridge_projectile = Value(328)
|
||||
final val frag_cartridge_projectile_b = Value(329)
|
||||
final val frag_grenade_projectile = Value(332)
|
||||
final val frag_grenade_projectile_enh = Value(333)
|
||||
final val galaxy_gunship_gun_projectile = Value(341)
|
||||
final val gauss_cannon_projectile = Value(348)
|
||||
final val grenade_projectile = Value(372)
|
||||
final val heavy_grenade_projectile = Value(392)
|
||||
final val heavy_rail_beam_projectile = Value(395)
|
||||
final val heavy_sniper_projectile = Value(397)
|
||||
final val hellfire_projectile = Value(400)
|
||||
final val hunter_seeker_missile_dumbfire = Value(404)
|
||||
final val hunter_seeker_missile_projectile = Value(405)
|
||||
final val jammer_cartridge_projectile = Value(414)
|
||||
final val jammer_cartridge_projectile_b = Value(415)
|
||||
final val jammer_grenade_projectile = Value(418)
|
||||
final val jammer_grenade_projectile_enh = Value(419)
|
||||
final val katana_projectile = Value(422)
|
||||
final val katana_projectileb = Value(423)
|
||||
final val lancer_projectile = Value(427)
|
||||
final val lasher_projectile = Value(430)
|
||||
final val lasher_projectile_ap = Value(431)
|
||||
final val bullet_105mm_projectile = Value(1)
|
||||
final val bullet_12mm_projectile = Value(4)
|
||||
final val bullet_12mm_projectileb = Value(5)
|
||||
final val bullet_150mm_projectile = Value(7)
|
||||
final val bullet_15mm_apc_projectile = Value(10)
|
||||
final val bullet_15mm_projectile = Value(11)
|
||||
final val bullet_20mm_apc_projectile = Value(17)
|
||||
final val bullet_20mm_projectile = Value(18)
|
||||
final val bullet_25mm_projectile = Value(20)
|
||||
final val bullet_35mm_projectile = Value(22)
|
||||
final val bullet_75mm_apc_projectile = Value(26)
|
||||
final val bullet_75mm_projectile = Value(27)
|
||||
final val bullet_9mm_AP_projectile = Value(30)
|
||||
final val bullet_9mm_projectile = Value(31)
|
||||
final val anniversary_projectilea = Value(58)
|
||||
final val anniversary_projectileb = Value(59)
|
||||
final val aphelion_immolation_cannon_projectile = Value(87)
|
||||
final val aphelion_laser_projectile = Value(91)
|
||||
final val aphelion_plasma_rocket_projectile = Value(99)
|
||||
final val aphelion_ppa_projectile = Value(103)
|
||||
final val aphelion_starfire_projectile = Value(108)
|
||||
final val bolt_projectile = Value(147)
|
||||
final val burster_projectile = Value(155)
|
||||
final val chainblade_projectile = Value(176)
|
||||
final val colossus_100mm_projectile = Value(181)
|
||||
final val colossus_burster_projectile = Value(188)
|
||||
final val colossus_chaingun_projectile = Value(193)
|
||||
final val colossus_cluster_bomb_projectile = Value(197)
|
||||
final val colossus_tank_cannon_projectile = Value(207)
|
||||
final val comet_projectile = Value(210)
|
||||
final val dualcycler_projectile = Value(266)
|
||||
final val dynomite_projectile = Value(268)
|
||||
final val energy_cell_projectile = Value(273)
|
||||
final val energy_gun_nc_projectile = Value(277)
|
||||
final val energy_gun_tr_projectile = Value(279)
|
||||
final val energy_gun_vs_projectile = Value(281)
|
||||
final val enhanced_energy_cell_projectile = Value(282)
|
||||
final val enhanced_quasar_projectile = Value(283)
|
||||
final val falcon_projectile = Value(286)
|
||||
final val firebird_missile_projectile = Value(288)
|
||||
final val flail_projectile = Value(296)
|
||||
final val flamethrower_fireball = Value(302)
|
||||
final val flamethrower_projectile = Value(303)
|
||||
final val flux_cannon_apc_projectile = Value(305)
|
||||
final val flux_cannon_thresher_projectile = Value(308)
|
||||
final val fluxpod_projectile = Value(311)
|
||||
final val forceblade_projectile = Value(325)
|
||||
final val frag_cartridge_projectile = Value(328)
|
||||
final val frag_cartridge_projectile_b = Value(329)
|
||||
final val frag_grenade_projectile = Value(332)
|
||||
final val frag_grenade_projectile_enh = Value(333)
|
||||
final val galaxy_gunship_gun_projectile = Value(341)
|
||||
final val gauss_cannon_projectile = Value(348)
|
||||
final val grenade_projectile = Value(372)
|
||||
final val heavy_grenade_projectile = Value(392)
|
||||
final val heavy_rail_beam_projectile = Value(395)
|
||||
final val heavy_sniper_projectile = Value(397)
|
||||
final val hellfire_projectile = Value(400)
|
||||
final val hunter_seeker_missile_dumbfire = Value(404)
|
||||
final val hunter_seeker_missile_projectile = Value(405)
|
||||
final val jammer_cartridge_projectile = Value(414)
|
||||
final val jammer_cartridge_projectile_b = Value(415)
|
||||
final val jammer_grenade_projectile = Value(418)
|
||||
final val jammer_grenade_projectile_enh = Value(419)
|
||||
final val katana_projectile = Value(422)
|
||||
final val katana_projectileb = Value(423)
|
||||
final val lancer_projectile = Value(427)
|
||||
final val lasher_projectile = Value(430)
|
||||
final val lasher_projectile_ap = Value(431)
|
||||
final val liberator_bomb_cluster_bomblet_projectile = Value(436)
|
||||
final val liberator_bomb_cluster_projectile = Value(437)
|
||||
final val liberator_bomb_projectile = Value(438)
|
||||
final val maelstrom_grenade_projectile = Value(465)
|
||||
final val maelstrom_grenade_projectile_contact = Value(466)
|
||||
final val maelstrom_stream_projectile = Value(467)
|
||||
final val magcutter_projectile = Value(469)
|
||||
final val melee_ammo_projectile = Value(541)
|
||||
final val meteor_common = Value(543)
|
||||
final val meteor_projectile_b_large = Value(544)
|
||||
final val meteor_projectile_b_medium = Value(545)
|
||||
final val meteor_projectile_b_small = Value(546)
|
||||
final val meteor_projectile_large = Value(547)
|
||||
final val meteor_projectile_medium = Value(548)
|
||||
final val meteor_projectile_small = Value(549)
|
||||
final val mine_projectile = Value(551)
|
||||
final val mine_sweeper_projectile = Value(554)
|
||||
final val mine_sweeper_projectile_enh = Value(555)
|
||||
final val oicw_little_buddy = Value(601)
|
||||
final val oicw_projectile = Value(602)
|
||||
final val pellet_gun_projectile = Value(631)
|
||||
final val peregrine_dual_machine_gun_projectile = Value(639)
|
||||
final val peregrine_mechhammer_projectile = Value(647)
|
||||
final val peregrine_particle_cannon_projectile = Value(654)
|
||||
final val peregrine_rocket_pod_projectile = Value(657)
|
||||
final val peregrine_sparrow_projectile = Value(661)
|
||||
final val phalanx_av_projectile = Value(665)
|
||||
final val phalanx_flak_projectile = Value(667)
|
||||
final val phalanx_projectile = Value(669)
|
||||
final val phoenix_missile_guided_projectile = Value(675)
|
||||
final val phoenix_missile_projectile = Value(676)
|
||||
final val plasma_cartridge_projectile = Value(678)
|
||||
final val plasma_cartridge_projectile_b = Value(679)
|
||||
final val plasma_grenade_projectile = Value(682)
|
||||
final val plasma_grenade_projectile_B = Value(683)
|
||||
final val pounder_projectile = Value(694)
|
||||
final val pounder_projectile_enh = Value(695)
|
||||
final val ppa_projectile = Value(696)
|
||||
final val pulsar_ap_projectile = Value(702)
|
||||
final val pulsar_projectile = Value(703)
|
||||
final val quasar_projectile = Value(713)
|
||||
final val radiator_grenade_projectile = Value(718)
|
||||
final val radiator_sticky_projectile = Value(719)
|
||||
final val reaver_rocket_projectile = Value(723)
|
||||
final val rocket_projectile = Value(735)
|
||||
final val rocklet_flak_projectile = Value(738)
|
||||
final val rocklet_jammer_projectile = Value(739)
|
||||
final val scattercannon_projectile = Value(746)
|
||||
final val scythe_projectile = Value(748)
|
||||
final val scythe_projectile_slave = Value(749)
|
||||
final val shotgun_shell_AP_projectile = Value(757)
|
||||
final val shotgun_shell_projectile = Value(758)
|
||||
final val six_shooter_projectile = Value(763)
|
||||
final val skyguard_flak_cannon_projectile = Value(787)
|
||||
final val sparrow_projectile = Value(792)
|
||||
final val sparrow_secondary_projectile = Value(793)
|
||||
final val spiker_projectile = Value(818)
|
||||
final val spitfire_aa_ammo_projectile = Value(821)
|
||||
final val spitfire_ammo_projectile = Value(824)
|
||||
final val starfire_projectile = Value(831)
|
||||
final val striker_missile_projectile = Value(840)
|
||||
final val striker_missile_targeting_projectile = Value(841)
|
||||
final val trek_projectile = Value(878)
|
||||
final val vanu_sentry_turret_projectile = Value(944)
|
||||
final val vulture_bomb_projectile = Value(988)
|
||||
final val vulture_nose_bullet_projectile = Value(989)
|
||||
final val vulture_tail_bullet_projectile = Value(991)
|
||||
final val wasp_gun_projectile = Value(999)
|
||||
final val wasp_rocket_projectile = Value(1001)
|
||||
final val winchester_projectile = Value(1005)
|
||||
final val liberator_bomb_cluster_projectile = Value(437)
|
||||
final val liberator_bomb_projectile = Value(438)
|
||||
final val maelstrom_grenade_projectile = Value(465)
|
||||
final val maelstrom_grenade_projectile_contact = Value(466)
|
||||
final val maelstrom_stream_projectile = Value(467)
|
||||
final val magcutter_projectile = Value(469)
|
||||
final val melee_ammo_projectile = Value(541)
|
||||
final val meteor_common = Value(543)
|
||||
final val meteor_projectile_b_large = Value(544)
|
||||
final val meteor_projectile_b_medium = Value(545)
|
||||
final val meteor_projectile_b_small = Value(546)
|
||||
final val meteor_projectile_large = Value(547)
|
||||
final val meteor_projectile_medium = Value(548)
|
||||
final val meteor_projectile_small = Value(549)
|
||||
final val mine_projectile = Value(551)
|
||||
final val mine_sweeper_projectile = Value(554)
|
||||
final val mine_sweeper_projectile_enh = Value(555)
|
||||
final val oicw_little_buddy = Value(601)
|
||||
final val oicw_projectile = Value(602)
|
||||
final val pellet_gun_projectile = Value(631)
|
||||
final val peregrine_dual_machine_gun_projectile = Value(639)
|
||||
final val peregrine_mechhammer_projectile = Value(647)
|
||||
final val peregrine_particle_cannon_projectile = Value(654)
|
||||
final val peregrine_rocket_pod_projectile = Value(657)
|
||||
final val peregrine_sparrow_projectile = Value(661)
|
||||
final val phalanx_av_projectile = Value(665)
|
||||
final val phalanx_flak_projectile = Value(667)
|
||||
final val phalanx_projectile = Value(669)
|
||||
final val phoenix_missile_guided_projectile = Value(675)
|
||||
final val phoenix_missile_projectile = Value(676)
|
||||
final val plasma_cartridge_projectile = Value(678)
|
||||
final val plasma_cartridge_projectile_b = Value(679)
|
||||
final val plasma_grenade_projectile = Value(682)
|
||||
final val plasma_grenade_projectile_B = Value(683)
|
||||
final val pounder_projectile = Value(694)
|
||||
final val pounder_projectile_enh = Value(695)
|
||||
final val ppa_projectile = Value(696)
|
||||
final val pulsar_ap_projectile = Value(702)
|
||||
final val pulsar_projectile = Value(703)
|
||||
final val quasar_projectile = Value(713)
|
||||
final val radiator_grenade_projectile = Value(718)
|
||||
final val radiator_sticky_projectile = Value(719)
|
||||
final val reaver_rocket_projectile = Value(723)
|
||||
final val rocket_projectile = Value(735)
|
||||
final val rocklet_flak_projectile = Value(738)
|
||||
final val rocklet_jammer_projectile = Value(739)
|
||||
final val scattercannon_projectile = Value(746)
|
||||
final val scythe_projectile = Value(748)
|
||||
final val scythe_projectile_slave = Value(749)
|
||||
final val shotgun_shell_AP_projectile = Value(757)
|
||||
final val shotgun_shell_projectile = Value(758)
|
||||
final val six_shooter_projectile = Value(763)
|
||||
final val skyguard_flak_cannon_projectile = Value(787)
|
||||
final val sparrow_projectile = Value(792)
|
||||
final val sparrow_secondary_projectile = Value(793)
|
||||
final val spiker_projectile = Value(818)
|
||||
final val spitfire_aa_ammo_projectile = Value(821)
|
||||
final val spitfire_ammo_projectile = Value(824)
|
||||
final val starfire_projectile = Value(831)
|
||||
final val striker_missile_projectile = Value(840)
|
||||
final val striker_missile_targeting_projectile = Value(841)
|
||||
final val trek_projectile = Value(878)
|
||||
final val vanu_sentry_turret_projectile = Value(944)
|
||||
final val vulture_bomb_projectile = Value(988)
|
||||
final val vulture_nose_bullet_projectile = Value(989)
|
||||
final val vulture_tail_bullet_projectile = Value(991)
|
||||
final val wasp_gun_projectile = Value(999)
|
||||
final val wasp_rocket_projectile = Value(1001)
|
||||
final val winchester_projectile = Value(1005)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ import net.psforever.types.Vector3
|
|||
* @param damage_model the kind of damage model to which the `target` is/was subject
|
||||
* @param hit_pos where the projectile hit
|
||||
*/
|
||||
final case class ResolvedProjectile(resolution : ProjectileResolution.Value,
|
||||
projectile : Projectile,
|
||||
target : SourceEntry,
|
||||
damage_model : DamageResistanceModel,
|
||||
hit_pos : Vector3) {
|
||||
val hit_time : Long = System.nanoTime
|
||||
final case class ResolvedProjectile(
|
||||
resolution: ProjectileResolution.Value,
|
||||
projectile: Projectile,
|
||||
target: SourceEntry,
|
||||
damage_model: DamageResistanceModel,
|
||||
hit_pos: Vector3
|
||||
) {
|
||||
val hit_time: Long = System.nanoTime
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,37 +10,38 @@ import net.psforever.objects.vital.resistance.ResistanceProfile
|
|||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
trait SourceEntry extends WorldEntity {
|
||||
def Name : String = ""
|
||||
def Definition : ObjectDefinition
|
||||
def CharId : Long = 0L
|
||||
def Faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
def Position_=(pos : Vector3) = Position
|
||||
def Orientation_=(pos : Vector3) = Position
|
||||
def Velocity_=(pos : Option[Vector3]) = Velocity
|
||||
def Modifiers : ResistanceProfile
|
||||
def Name: String = ""
|
||||
def Definition: ObjectDefinition
|
||||
def CharId: Long = 0L
|
||||
def Faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
def Position_=(pos: Vector3) = Position
|
||||
def Orientation_=(pos: Vector3) = Position
|
||||
def Velocity_=(pos: Option[Vector3]) = Velocity
|
||||
def Modifiers: ResistanceProfile
|
||||
}
|
||||
|
||||
object SourceEntry {
|
||||
final val None = new SourceEntry() {
|
||||
def Definition = null
|
||||
def Position = Vector3.Zero
|
||||
def Definition = null
|
||||
def Position = Vector3.Zero
|
||||
def Orientation = Vector3.Zero
|
||||
def Velocity = Some(Vector3.Zero)
|
||||
def Modifiers = null
|
||||
def Velocity = Some(Vector3.Zero)
|
||||
def Modifiers = null
|
||||
}
|
||||
|
||||
def apply(target : PlanetSideGameObject with FactionAffinity) : SourceEntry = {
|
||||
def apply(target: PlanetSideGameObject with FactionAffinity): SourceEntry = {
|
||||
target match {
|
||||
case obj : Player => PlayerSource(obj)
|
||||
case obj : Vehicle => VehicleSource(obj)
|
||||
case obj : ComplexDeployable => ComplexDeployableSource(obj)
|
||||
case obj : SimpleDeployable => DeployableSource(obj)
|
||||
case _ => ObjectSource(target)
|
||||
case obj: Player => PlayerSource(obj)
|
||||
case obj: Vehicle => VehicleSource(obj)
|
||||
case obj: ComplexDeployable => ComplexDeployableSource(obj)
|
||||
case obj: SimpleDeployable => DeployableSource(obj)
|
||||
case _ => ObjectSource(target)
|
||||
}
|
||||
}
|
||||
|
||||
def NameFormat(name : String) : String = {
|
||||
name.replace("_", " ")
|
||||
def NameFormat(name: String): String = {
|
||||
name
|
||||
.replace("_", " ")
|
||||
.split(" ")
|
||||
.map(_.capitalize)
|
||||
.mkString(" ")
|
||||
|
|
|
|||
|
|
@ -6,27 +6,29 @@ import net.psforever.objects.definition.VehicleDefinition
|
|||
import net.psforever.objects.vital.resistance.ResistanceProfile
|
||||
import net.psforever.types.{PlanetSideEmpire, Vector3}
|
||||
|
||||
final case class VehicleSource(obj_def : VehicleDefinition,
|
||||
faction : PlanetSideEmpire.Value,
|
||||
health : Int,
|
||||
shields : Int,
|
||||
position : Vector3,
|
||||
orientation : Vector3,
|
||||
velocity : Option[Vector3],
|
||||
modifiers : ResistanceProfile) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition : VehicleDefinition = obj_def
|
||||
def Health = health
|
||||
def Shields = shields
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = modifiers
|
||||
final case class VehicleSource(
|
||||
obj_def: VehicleDefinition,
|
||||
faction: PlanetSideEmpire.Value,
|
||||
health: Int,
|
||||
shields: Int,
|
||||
position: Vector3,
|
||||
orientation: Vector3,
|
||||
velocity: Option[Vector3],
|
||||
modifiers: ResistanceProfile
|
||||
) extends SourceEntry {
|
||||
override def Name = SourceEntry.NameFormat(obj_def.Name)
|
||||
override def Faction = faction
|
||||
def Definition: VehicleDefinition = obj_def
|
||||
def Health = health
|
||||
def Shields = shields
|
||||
def Position = position
|
||||
def Orientation = orientation
|
||||
def Velocity = velocity
|
||||
def Modifiers = modifiers
|
||||
}
|
||||
|
||||
object VehicleSource {
|
||||
def apply(obj : Vehicle) : VehicleSource = {
|
||||
def apply(obj: Vehicle): VehicleSource = {
|
||||
VehicleSource(
|
||||
obj.Definition,
|
||||
obj.Faction,
|
||||
|
|
|
|||
|
|
@ -4,19 +4,18 @@ package net.psforever.objects.ce
|
|||
import net.psforever.objects.definition.ComplexDeployableDefinition
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
|
||||
abstract class ComplexDeployable(cdef : ComplexDeployableDefinition) extends PlanetSideServerObject
|
||||
with Deployable {
|
||||
private var shields : Int = 0
|
||||
abstract class ComplexDeployable(cdef: ComplexDeployableDefinition) extends PlanetSideServerObject with Deployable {
|
||||
private var shields: Int = 0
|
||||
|
||||
def Shields : Int = shields
|
||||
def Shields: Int = shields
|
||||
|
||||
def Shields_=(toShields : Int) : Int = {
|
||||
def Shields_=(toShields: Int): Int = {
|
||||
shields = math.min(math.max(0, toShields), MaxShields)
|
||||
Shields
|
||||
}
|
||||
|
||||
def MaxShields : Int = {
|
||||
0//Definition.MaxShields
|
||||
def MaxShields: Int = {
|
||||
0 //Definition.MaxShields
|
||||
}
|
||||
|
||||
def Definition = cdef
|
||||
|
|
|
|||
|
|
@ -9,83 +9,80 @@ import net.psforever.objects.zones.ZoneAware
|
|||
import net.psforever.packet.game.DeployableIcon
|
||||
import net.psforever.types.PlanetSideEmpire
|
||||
|
||||
trait Deployable extends FactionAffinity
|
||||
with Vitality
|
||||
with OwnableByPlayer
|
||||
with ZoneAware {
|
||||
this : PlanetSideGameObject =>
|
||||
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
trait Deployable extends FactionAffinity with Vitality with OwnableByPlayer with ZoneAware {
|
||||
this: PlanetSideGameObject =>
|
||||
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
|
||||
|
||||
def MaxHealth : Int
|
||||
def MaxHealth: Int
|
||||
|
||||
def Faction : PlanetSideEmpire.Value = faction
|
||||
def Faction: PlanetSideEmpire.Value = faction
|
||||
|
||||
override def Faction_=(toFaction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
|
||||
override def Faction_=(toFaction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
|
||||
faction = toFaction
|
||||
Faction
|
||||
}
|
||||
|
||||
def DamageModel : DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
|
||||
def DamageModel: DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
|
||||
|
||||
def Definition : DeployableDefinition
|
||||
def Definition: DeployableDefinition
|
||||
}
|
||||
|
||||
object Deployable {
|
||||
object Category {
|
||||
def Of(item : DeployedItem.Value) : DeployableCategory.Value = deployablesToCategories(item)
|
||||
def Of(item: DeployedItem.Value): DeployableCategory.Value = deployablesToCategories(item)
|
||||
|
||||
def Includes(category : DeployableCategory.Value) : List[DeployedItem.Value] = {
|
||||
def Includes(category: DeployableCategory.Value): List[DeployedItem.Value] = {
|
||||
(for {
|
||||
(ce, cat) <- deployablesToCategories
|
||||
if cat == category
|
||||
} yield ce) toList
|
||||
}
|
||||
|
||||
def OfAll() : Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories
|
||||
def OfAll(): Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories
|
||||
|
||||
private val deployablesToCategories : Map[DeployedItem.Value, DeployableCategory.Value] = Map(
|
||||
DeployedItem.boomer -> DeployableCategory.Boomers,
|
||||
DeployedItem.he_mine -> DeployableCategory.Mines,
|
||||
DeployedItem.jammer_mine -> DeployableCategory.Mines,
|
||||
DeployedItem.spitfire_turret -> DeployableCategory.SmallTurrets,
|
||||
DeployedItem.motionalarmsensor -> DeployableCategory.Sensors,
|
||||
DeployedItem.spitfire_cloaked -> DeployableCategory.SmallTurrets,
|
||||
DeployedItem.spitfire_aa -> DeployableCategory.SmallTurrets,
|
||||
private val deployablesToCategories: Map[DeployedItem.Value, DeployableCategory.Value] = Map(
|
||||
DeployedItem.boomer -> DeployableCategory.Boomers,
|
||||
DeployedItem.he_mine -> DeployableCategory.Mines,
|
||||
DeployedItem.jammer_mine -> DeployableCategory.Mines,
|
||||
DeployedItem.spitfire_turret -> DeployableCategory.SmallTurrets,
|
||||
DeployedItem.motionalarmsensor -> DeployableCategory.Sensors,
|
||||
DeployedItem.spitfire_cloaked -> DeployableCategory.SmallTurrets,
|
||||
DeployedItem.spitfire_aa -> DeployableCategory.SmallTurrets,
|
||||
DeployedItem.deployable_shield_generator -> DeployableCategory.ShieldGenerators,
|
||||
DeployedItem.tank_traps -> DeployableCategory.TankTraps,
|
||||
DeployedItem.portable_manned_turret -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_nc -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_tr -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_vs -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.sensor_shield -> DeployableCategory.Sensors,
|
||||
DeployedItem.router_telepad_deployable -> DeployableCategory.Telepads
|
||||
DeployedItem.tank_traps -> DeployableCategory.TankTraps,
|
||||
DeployedItem.portable_manned_turret -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_nc -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_tr -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.portable_manned_turret_vs -> DeployableCategory.FieldTurrets,
|
||||
DeployedItem.sensor_shield -> DeployableCategory.Sensors,
|
||||
DeployedItem.router_telepad_deployable -> DeployableCategory.Telepads
|
||||
)
|
||||
}
|
||||
|
||||
object Icon {
|
||||
def apply(item : DeployedItem.Value) : DeployableIcon.Value = ceicon(item.id)
|
||||
def apply(item: DeployedItem.Value): DeployableIcon.Value = ceicon(item.id)
|
||||
|
||||
private val ceicon : Map[Int, DeployableIcon.Value] = Map(
|
||||
DeployedItem.boomer.id -> DeployableIcon.Boomer,
|
||||
DeployedItem.he_mine.id -> DeployableIcon.HEMine,
|
||||
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
|
||||
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
|
||||
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
|
||||
DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
|
||||
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
|
||||
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
|
||||
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
|
||||
DeployedItem.portable_manned_turret.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
|
||||
private val ceicon: Map[Int, DeployableIcon.Value] = Map(
|
||||
DeployedItem.boomer.id -> DeployableIcon.Boomer,
|
||||
DeployedItem.he_mine.id -> DeployableIcon.HEMine,
|
||||
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
|
||||
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
|
||||
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
|
||||
DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
|
||||
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
|
||||
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
|
||||
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
|
||||
DeployedItem.portable_manned_turret.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
|
||||
DeployedItem.deployable_shield_generator.id -> DeployableIcon.AegisShieldGenerator,
|
||||
DeployedItem.router_telepad_deployable.id -> DeployableIcon.RouterTelepad
|
||||
DeployedItem.router_telepad_deployable.id -> DeployableIcon.RouterTelepad
|
||||
).withDefaultValue(DeployableIcon.Boomer)
|
||||
}
|
||||
|
||||
object UI {
|
||||
def apply(item : DeployedItem.Value) : (Int, Int) = planetsideAttribute(item)
|
||||
def apply(item: DeployedItem.Value): (Int, Int) = planetsideAttribute(item)
|
||||
|
||||
/**
|
||||
* The attribute values to be invoked in `PlanetsideAttributeMessage` packets
|
||||
|
|
@ -93,21 +90,21 @@ object Deployable {
|
|||
* The first number is for the actual count field.
|
||||
* The second number is for the maximum count field.
|
||||
*/
|
||||
private val planetsideAttribute : Map[DeployedItem.Value, (Int, Int)] = Map(
|
||||
DeployedItem.boomer -> (94, 83),
|
||||
DeployedItem.he_mine -> (95, 84),
|
||||
DeployedItem.jammer_mine -> (96, 85),
|
||||
DeployedItem.spitfire_turret -> (97, 86),
|
||||
DeployedItem.motionalarmsensor -> (98, 87),
|
||||
DeployedItem.spitfire_cloaked -> (99, 88),
|
||||
DeployedItem.spitfire_aa -> (100, 89),
|
||||
private val planetsideAttribute: Map[DeployedItem.Value, (Int, Int)] = Map(
|
||||
DeployedItem.boomer -> (94, 83),
|
||||
DeployedItem.he_mine -> (95, 84),
|
||||
DeployedItem.jammer_mine -> (96, 85),
|
||||
DeployedItem.spitfire_turret -> (97, 86),
|
||||
DeployedItem.motionalarmsensor -> (98, 87),
|
||||
DeployedItem.spitfire_cloaked -> (99, 88),
|
||||
DeployedItem.spitfire_aa -> (100, 89),
|
||||
DeployedItem.deployable_shield_generator -> (101, 90),
|
||||
DeployedItem.tank_traps -> (102, 91),
|
||||
DeployedItem.portable_manned_turret -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_nc -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_tr -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_vs -> (103, 92),
|
||||
DeployedItem.sensor_shield -> (104, 93)
|
||||
).withDefaultValue((0,0))
|
||||
DeployedItem.tank_traps -> (102, 91),
|
||||
DeployedItem.portable_manned_turret -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_nc -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_tr -> (103, 92),
|
||||
DeployedItem.portable_manned_turret_vs -> (103, 92),
|
||||
DeployedItem.sensor_shield -> (104, 93)
|
||||
).withDefaultValue((0, 0))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,14 +4,5 @@ package net.psforever.objects.ce
|
|||
object DeployableCategory extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
val
|
||||
Boomers,
|
||||
Mines,
|
||||
SmallTurrets,
|
||||
Sensors,
|
||||
TankTraps,
|
||||
FieldTurrets,
|
||||
ShieldGenerators,
|
||||
Telepads
|
||||
= Value
|
||||
val Boomers, Mines, SmallTurrets, Sensors, TankTraps, FieldTurrets, ShieldGenerators, Telepads = Value
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@ package net.psforever.objects.ce
|
|||
object DeployedItem extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
final val boomer = Value(148)
|
||||
final val boomer = Value(148)
|
||||
final val deployable_shield_generator = Value(240)
|
||||
final val he_mine = Value(388)
|
||||
final val jammer_mine = Value(420) //disruptor mine
|
||||
final val motionalarmsensor = Value(575)
|
||||
final val sensor_shield = Value(752) //sensor disruptor
|
||||
final val spitfire_aa = Value(819) //cerebus turret
|
||||
final val spitfire_cloaked = Value(825) //shadow turret
|
||||
final val spitfire_turret = Value(826)
|
||||
final val tank_traps = Value(849) //trap
|
||||
final val portable_manned_turret = Value(685)
|
||||
final val portable_manned_turret_nc = Value(686)
|
||||
final val portable_manned_turret_tr = Value(687)
|
||||
final val portable_manned_turret_vs = Value(688)
|
||||
final val router_telepad_deployable = Value(744)
|
||||
final val he_mine = Value(388)
|
||||
final val jammer_mine = Value(420) //disruptor mine
|
||||
final val motionalarmsensor = Value(575)
|
||||
final val sensor_shield = Value(752) //sensor disruptor
|
||||
final val spitfire_aa = Value(819) //cerebus turret
|
||||
final val spitfire_cloaked = Value(825) //shadow turret
|
||||
final val spitfire_turret = Value(826)
|
||||
final val tank_traps = Value(849) //trap
|
||||
final val portable_manned_turret = Value(685)
|
||||
final val portable_manned_turret_nc = Value(686)
|
||||
final val portable_manned_turret_tr = Value(687)
|
||||
final val portable_manned_turret_vs = Value(688)
|
||||
final val router_telepad_deployable = Value(744)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ package net.psforever.objects.ce
|
|||
import net.psforever.objects.PlanetSideGameObject
|
||||
import net.psforever.objects.definition.SimpleDeployableDefinition
|
||||
|
||||
abstract class SimpleDeployable(cdef : SimpleDeployableDefinition) extends PlanetSideGameObject
|
||||
with Deployable {
|
||||
abstract class SimpleDeployable(cdef: SimpleDeployableDefinition) extends PlanetSideGameObject with Deployable {
|
||||
Health = Definition.MaxHealth
|
||||
|
||||
def Definition = cdef
|
||||
|
|
|
|||
|
|
@ -10,37 +10,37 @@ import net.psforever.objects.zones.Zone
|
|||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
trait TelepadLike {
|
||||
private var router : Option[PlanetSideGUID] = None
|
||||
private var activated : Boolean = false
|
||||
private var router: Option[PlanetSideGUID] = None
|
||||
private var activated: Boolean = false
|
||||
|
||||
def Router : Option[PlanetSideGUID] = router
|
||||
def Router: Option[PlanetSideGUID] = router
|
||||
|
||||
def Router_=(rguid : PlanetSideGUID) : Option[PlanetSideGUID] = Router_=(Some(rguid))
|
||||
def Router_=(rguid: PlanetSideGUID): Option[PlanetSideGUID] = Router_=(Some(rguid))
|
||||
|
||||
def Router_=(rguid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
|
||||
def Router_=(rguid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
|
||||
router match {
|
||||
case None =>
|
||||
router = rguid
|
||||
case Some(_) =>
|
||||
if(rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
|
||||
if (rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
|
||||
router = None
|
||||
}
|
||||
}
|
||||
Router
|
||||
}
|
||||
|
||||
def Active : Boolean = activated
|
||||
def Active: Boolean = activated
|
||||
|
||||
def Active_=(state : Boolean) : Boolean = {
|
||||
def Active_=(state: Boolean): Boolean = {
|
||||
activated = state
|
||||
Active
|
||||
}
|
||||
}
|
||||
|
||||
object TelepadLike {
|
||||
final case class Activate(obj : PlanetSideGameObject with TelepadLike)
|
||||
final case class Activate(obj: PlanetSideGameObject with TelepadLike)
|
||||
|
||||
final case class Deactivate(obj : PlanetSideGameObject with TelepadLike)
|
||||
final case class Deactivate(obj: PlanetSideGameObject with TelepadLike)
|
||||
|
||||
/**
|
||||
* Assemble some logic for a provided object.
|
||||
|
|
@ -48,10 +48,10 @@ object TelepadLike {
|
|||
* anticipating a `Terminal` object using this same definition
|
||||
* @param context hook to the local `Actor` system
|
||||
*/
|
||||
def Setup(obj : Amenity, context : ActorContext) : Unit = {
|
||||
def Setup(obj: Amenity, context: ActorContext): Unit = {
|
||||
obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID
|
||||
import akka.actor.Props
|
||||
if(obj.Actor == Default.Actor) {
|
||||
if (obj.Actor == Default.Actor) {
|
||||
obj.Actor = context.actorOf(Props(classOf[TelepadControl], obj), PlanetSideServerObject.UniqueActorName(obj))
|
||||
}
|
||||
}
|
||||
|
|
@ -64,20 +64,19 @@ object TelepadLike {
|
|||
* @param zone where the router is located
|
||||
* @return the pair of units that compose the teleportation system
|
||||
*/
|
||||
def AppraiseTeleportationSystem(router : Vehicle, zone : Zone) : Option[(Utility.InternalTelepad, TelepadDeployable)] = {
|
||||
def AppraiseTeleportationSystem(router: Vehicle, zone: Zone): Option[(Utility.InternalTelepad, TelepadDeployable)] = {
|
||||
import net.psforever.objects.vehicles.UtilityType
|
||||
import net.psforever.types.DriveState
|
||||
router.Utility(UtilityType.internal_router_telepad_deployable) match {
|
||||
//if the vehicle has an internal telepad, it is allowed to be a Router (that's a weird way of saying it)
|
||||
case Some(util : Utility.InternalTelepad) =>
|
||||
case Some(util: Utility.InternalTelepad) =>
|
||||
//check for a readied remote telepad
|
||||
zone.GUID(util.Telepad) match {
|
||||
case Some(telepad : TelepadDeployable) =>
|
||||
case Some(telepad: TelepadDeployable) =>
|
||||
//determine whether to activate both the Router's internal telepad and the deployed remote telepad
|
||||
if(router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
|
||||
if (router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
|
||||
Some((util, telepad))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
case _ =>
|
||||
|
|
@ -96,8 +95,8 @@ object TelepadLike {
|
|||
* a placeholder like this is easy to reason around.
|
||||
* @param obj an entity that extends `TelepadLike`
|
||||
*/
|
||||
class TelepadControl(obj : TelepadLike) extends akka.actor.Actor {
|
||||
def receive : akka.actor.Actor.Receive = {
|
||||
class TelepadControl(obj: TelepadLike) extends akka.actor.Actor {
|
||||
def receive: akka.actor.Actor.Receive = {
|
||||
case _ => ;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,19 +4,19 @@ package net.psforever.objects.definition
|
|||
import net.psforever.objects.definition.converter.AmmoBoxConverter
|
||||
import net.psforever.objects.equipment.Ammo
|
||||
|
||||
class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||
class AmmoBoxDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
private val ammoType : Ammo.Value = Ammo(objectId) //let throw NoSuchElementException
|
||||
private var capacity : Int = 1
|
||||
private val ammoType: Ammo.Value = Ammo(objectId) //let throw NoSuchElementException
|
||||
private var capacity: Int = 1
|
||||
Name = "ammo box"
|
||||
Size = EquipmentSize.Inventory
|
||||
Packet = AmmoBoxDefinition.converter
|
||||
|
||||
def AmmoType : Ammo.Value = ammoType
|
||||
def AmmoType: Ammo.Value = ammoType
|
||||
|
||||
def Capacity : Int = capacity
|
||||
def Capacity: Int = capacity
|
||||
|
||||
def Capacity_=(capacity : Int) : Int = {
|
||||
def Capacity_=(capacity: Int): Int = {
|
||||
this.capacity = capacity
|
||||
Capacity
|
||||
}
|
||||
|
|
@ -25,11 +25,11 @@ class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
|||
object AmmoBoxDefinition {
|
||||
private val converter = new AmmoBoxConverter()
|
||||
|
||||
def apply(objectId: Int) : AmmoBoxDefinition = {
|
||||
def apply(objectId: Int): AmmoBoxDefinition = {
|
||||
new AmmoBoxDefinition(objectId)
|
||||
}
|
||||
|
||||
def apply(ammoType : Ammo.Value) : AmmoBoxDefinition = {
|
||||
def apply(ammoType: Ammo.Value): AmmoBoxDefinition = {
|
||||
new AmmoBoxDefinition(ammoType.id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@ import net.psforever.objects.vital.VitalityDefinition
|
|||
* The definition for game objects that look like other people, and also for players.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||
with VitalityDefinition {
|
||||
class AvatarDefinition(objectId: Int) extends ObjectDefinition(objectId) with VitalityDefinition {
|
||||
Avatars(objectId) //let throw NoSuchElementException
|
||||
Packet = AvatarDefinition.converter
|
||||
}
|
||||
|
|
@ -18,11 +17,11 @@ class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
|||
object AvatarDefinition {
|
||||
private val converter = new AvatarConverter()
|
||||
|
||||
def apply(objectId: Int) : AvatarDefinition = {
|
||||
def apply(objectId: Int): AvatarDefinition = {
|
||||
new AvatarDefinition(objectId)
|
||||
}
|
||||
|
||||
def apply(avatar : Avatars.Value) : AvatarDefinition = {
|
||||
def apply(avatar: Avatars.Value): AvatarDefinition = {
|
||||
new AvatarDefinition(avatar.id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,21 @@
|
|||
package net.psforever.objects.definition
|
||||
|
||||
abstract class BasicDefinition {
|
||||
private var name : String = "definition"
|
||||
private var descriptor : Option[String] = None
|
||||
private var name: String = "definition"
|
||||
private var descriptor: Option[String] = None
|
||||
|
||||
def Name : String = name
|
||||
def Name: String = name
|
||||
|
||||
def Name_=(name : String) : String = {
|
||||
def Name_=(name: String): String = {
|
||||
this.name = name
|
||||
Name
|
||||
}
|
||||
|
||||
def Descriptor : String = descriptor.getOrElse(Name)
|
||||
def Descriptor: String = descriptor.getOrElse(Name)
|
||||
|
||||
def Descriptor_=(description : String) : String = Descriptor_=(Some(description))
|
||||
def Descriptor_=(description: String): String = Descriptor_=(Some(description))
|
||||
|
||||
def Descriptor_=(description : Option[String]) : String = {
|
||||
def Descriptor_=(description: Option[String]): String = {
|
||||
descriptor = description
|
||||
Descriptor
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,26 +7,28 @@ import net.psforever.objects.vehicles.CargoVehicleRestriction
|
|||
* The definition for a cargo hold.
|
||||
*/
|
||||
class CargoDefinition extends BasicDefinition {
|
||||
|
||||
/** a restriction on the type of exo-suit a person can wear */
|
||||
private var vehicleRestriction : CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
|
||||
private var vehicleRestriction: CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
|
||||
|
||||
/** the user can escape while the vehicle is moving */
|
||||
private var bailable : Boolean = true
|
||||
private var bailable: Boolean = true
|
||||
Name = "cargo"
|
||||
|
||||
def CargoRestriction : CargoVehicleRestriction.Value = {
|
||||
def CargoRestriction: CargoVehicleRestriction.Value = {
|
||||
this.vehicleRestriction
|
||||
}
|
||||
|
||||
def CargoRestriction_=(restriction : CargoVehicleRestriction.Value) : CargoVehicleRestriction.Value = {
|
||||
def CargoRestriction_=(restriction: CargoVehicleRestriction.Value): CargoVehicleRestriction.Value = {
|
||||
this.vehicleRestriction = restriction
|
||||
restriction
|
||||
}
|
||||
|
||||
def Bailable : Boolean = {
|
||||
def Bailable: Boolean = {
|
||||
this.bailable
|
||||
}
|
||||
|
||||
def Bailable_=(canBail : Boolean) : Boolean = {
|
||||
def Bailable_=(canBail: Boolean): Boolean = {
|
||||
this.bailable = canBail
|
||||
canBail
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,39 +8,39 @@ import net.psforever.types.CertificationType
|
|||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
class ConstructionItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||
class ConstructionItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
|
||||
CItem(objectId) //let throw NoSuchElementException
|
||||
private val modes : ListBuffer[ConstructionFireMode] = ListBuffer()
|
||||
private val modes: ListBuffer[ConstructionFireMode] = ListBuffer()
|
||||
Packet = new ACEConverter
|
||||
|
||||
def Modes : ListBuffer[ConstructionFireMode] = modes
|
||||
def Modes: ListBuffer[ConstructionFireMode] = modes
|
||||
}
|
||||
|
||||
object ConstructionItemDefinition {
|
||||
def apply(objectId : Int) : ConstructionItemDefinition = {
|
||||
def apply(objectId: Int): ConstructionItemDefinition = {
|
||||
new ConstructionItemDefinition(objectId)
|
||||
}
|
||||
|
||||
def apply(cItem : CItem.Value) : ConstructionItemDefinition = {
|
||||
def apply(cItem: CItem.Value): ConstructionItemDefinition = {
|
||||
new ConstructionItemDefinition(cItem.id)
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructionFireMode {
|
||||
private val deployables : ListBuffer[DeployedItem.Value] = ListBuffer.empty
|
||||
private val permissions : ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty
|
||||
private val deployables: ListBuffer[DeployedItem.Value] = ListBuffer.empty
|
||||
private val permissions: ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty
|
||||
|
||||
def Permissions : ListBuffer[Set[CertificationType.Value]] = permissions
|
||||
def Permissions: ListBuffer[Set[CertificationType.Value]] = permissions
|
||||
|
||||
def Deployables : ListBuffer[DeployedItem.Value] = deployables
|
||||
def Deployables: ListBuffer[DeployedItem.Value] = deployables
|
||||
|
||||
def Item(deployable : DeployedItem.Value) : ListBuffer[DeployedItem.Value] = {
|
||||
def Item(deployable: DeployedItem.Value): ListBuffer[DeployedItem.Value] = {
|
||||
deployables += deployable
|
||||
permissions += Set.empty[CertificationType.Value]
|
||||
deployables
|
||||
}
|
||||
|
||||
def Item(deployPair : (DeployedItem.Value, Set[CertificationType.Value])) : ListBuffer[DeployedItem.Value] = {
|
||||
def Item(deployPair: (DeployedItem.Value, Set[CertificationType.Value])): ListBuffer[DeployedItem.Value] = {
|
||||
val (deployable, permission) = deployPair
|
||||
deployables += deployable
|
||||
permissions += permission
|
||||
|
|
|
|||
|
|
@ -8,31 +8,34 @@ import net.psforever.objects.inventory.InventoryTile
|
|||
* The definition for any piece of `Equipment`.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
abstract class EquipmentDefinition(objectId : Int) extends ObjectDefinition(objectId) {
|
||||
abstract class EquipmentDefinition(objectId: Int) extends ObjectDefinition(objectId) {
|
||||
|
||||
/** the size of the item when placed in an EquipmentSlot / holster / mounting */
|
||||
private var size : EquipmentSize.Value = EquipmentSize.Blocked
|
||||
private var size: EquipmentSize.Value = EquipmentSize.Blocked
|
||||
|
||||
/** the size of the item when placed in the grid inventory space */
|
||||
private var tile : InventoryTile = InventoryTile.Tile11
|
||||
private var tile: InventoryTile = InventoryTile.Tile11
|
||||
|
||||
/** a correction for the z-coordinate for some dropped items to avoid sinking into the ground */
|
||||
private var dropOffset : Float = 0f
|
||||
private var dropOffset: Float = 0f
|
||||
|
||||
def Size : EquipmentSize.Value = size
|
||||
def Size: EquipmentSize.Value = size
|
||||
|
||||
def Size_=(newSize : EquipmentSize.Value) : EquipmentSize.Value = {
|
||||
def Size_=(newSize: EquipmentSize.Value): EquipmentSize.Value = {
|
||||
size = newSize
|
||||
Size
|
||||
}
|
||||
|
||||
def Tile : InventoryTile = tile
|
||||
def Tile: InventoryTile = tile
|
||||
|
||||
def Tile_=(newTile : InventoryTile) : InventoryTile = {
|
||||
def Tile_=(newTile: InventoryTile): InventoryTile = {
|
||||
tile = newTile
|
||||
Tile
|
||||
}
|
||||
|
||||
def DropOffset : Float = dropOffset
|
||||
def DropOffset: Float = dropOffset
|
||||
|
||||
def DropOffset(offset : Float) : Float = {
|
||||
def DropOffset(offset: Float): Float = {
|
||||
dropOffset = offset
|
||||
DropOffset
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,112 +13,112 @@ import net.psforever.types.{CertificationType, ExoSuitType, PlanetSideEmpire}
|
|||
* Players are influenced by the exo-suit they wear in a variety of ways, with speed and available equipment slots being major differences.
|
||||
* @param suitType the `Enumeration` corresponding to this exo-suit
|
||||
*/
|
||||
class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicDefinition
|
||||
with ResistanceProfileMutators
|
||||
with DamageResistanceModel {
|
||||
protected var permissions : List[CertificationType.Value] = List.empty
|
||||
protected var maxArmor : Int = 0
|
||||
protected val holsters : Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked)
|
||||
protected var inventoryScale : InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile
|
||||
protected var inventoryOffset : Int = 0
|
||||
protected var maxCapacitor : Int = 0
|
||||
protected var capacitorRechargeDelayMillis : Int = 0
|
||||
protected var capacitorRechargePerSecond : Int = 0
|
||||
protected var capacitorDrainPerSecond : Int = 0
|
||||
class ExoSuitDefinition(private val suitType: ExoSuitType.Value)
|
||||
extends BasicDefinition
|
||||
with ResistanceProfileMutators
|
||||
with DamageResistanceModel {
|
||||
protected var permissions: List[CertificationType.Value] = List.empty
|
||||
protected var maxArmor: Int = 0
|
||||
protected val holsters: Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked)
|
||||
protected var inventoryScale: InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile
|
||||
protected var inventoryOffset: Int = 0
|
||||
protected var maxCapacitor: Int = 0
|
||||
protected var capacitorRechargeDelayMillis: Int = 0
|
||||
protected var capacitorRechargePerSecond: Int = 0
|
||||
protected var capacitorDrainPerSecond: Int = 0
|
||||
Name = "exo-suit"
|
||||
DamageUsing = StandardInfantryDamage
|
||||
ResistUsing = StandardInfantryResistance
|
||||
Model = StandardResolutions.Infantry
|
||||
|
||||
def SuitType : ExoSuitType.Value = suitType
|
||||
def SuitType: ExoSuitType.Value = suitType
|
||||
|
||||
def MaxArmor : Int = maxArmor
|
||||
def MaxArmor: Int = maxArmor
|
||||
|
||||
def MaxArmor_=(armor : Int) : Int = {
|
||||
def MaxArmor_=(armor: Int): Int = {
|
||||
maxArmor = math.min(math.max(0, armor), 65535)
|
||||
MaxArmor
|
||||
}
|
||||
|
||||
def MaxCapacitor : Int = maxCapacitor
|
||||
def MaxCapacitor: Int = maxCapacitor
|
||||
|
||||
def MaxCapacitor_=(value : Int) : Int = {
|
||||
def MaxCapacitor_=(value: Int): Int = {
|
||||
maxCapacitor = value
|
||||
maxCapacitor
|
||||
}
|
||||
|
||||
def CapacitorRechargeDelayMillis : Int = capacitorRechargeDelayMillis
|
||||
def CapacitorRechargeDelayMillis: Int = capacitorRechargeDelayMillis
|
||||
|
||||
def CapacitorRechargeDelayMillis_=(value : Int) : Int = {
|
||||
def CapacitorRechargeDelayMillis_=(value: Int): Int = {
|
||||
capacitorRechargeDelayMillis = value
|
||||
capacitorRechargeDelayMillis
|
||||
}
|
||||
|
||||
def CapacitorRechargePerSecond : Int = capacitorRechargePerSecond
|
||||
def CapacitorRechargePerSecond: Int = capacitorRechargePerSecond
|
||||
|
||||
def CapacitorRechargePerSecond_=(value : Int) : Int = {
|
||||
def CapacitorRechargePerSecond_=(value: Int): Int = {
|
||||
capacitorRechargePerSecond = value
|
||||
capacitorRechargePerSecond
|
||||
}
|
||||
|
||||
def CapacitorDrainPerSecond : Int = capacitorDrainPerSecond
|
||||
def CapacitorDrainPerSecond: Int = capacitorDrainPerSecond
|
||||
|
||||
def CapacitorDrainPerSecond_=(value : Int) : Int = {
|
||||
def CapacitorDrainPerSecond_=(value: Int): Int = {
|
||||
capacitorDrainPerSecond = value
|
||||
capacitorDrainPerSecond
|
||||
}
|
||||
|
||||
def InventoryScale : InventoryTile = inventoryScale
|
||||
def InventoryScale: InventoryTile = inventoryScale
|
||||
|
||||
def InventoryScale_=(scale : InventoryTile) : InventoryTile = {
|
||||
def InventoryScale_=(scale: InventoryTile): InventoryTile = {
|
||||
inventoryScale = scale
|
||||
InventoryScale
|
||||
}
|
||||
|
||||
def InventoryOffset : Int = inventoryOffset
|
||||
def InventoryOffset: Int = inventoryOffset
|
||||
|
||||
def InventoryOffset_=(offset : Int) : Int = {
|
||||
def InventoryOffset_=(offset: Int): Int = {
|
||||
inventoryOffset = math.min(math.max(0, offset), 65535)
|
||||
InventoryOffset
|
||||
}
|
||||
|
||||
def Holsters : Array[EquipmentSize.Value] = holsters
|
||||
def Holsters: Array[EquipmentSize.Value] = holsters
|
||||
|
||||
def Holster(slot : Int) : EquipmentSize.Value = {
|
||||
if(slot >= 0 && slot < 5) {
|
||||
def Holster(slot: Int): EquipmentSize.Value = {
|
||||
if (slot >= 0 && slot < 5) {
|
||||
holsters(slot)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
EquipmentSize.Blocked
|
||||
}
|
||||
}
|
||||
|
||||
def Holster(slot : Int, value : EquipmentSize.Value) : EquipmentSize.Value = {
|
||||
if(slot >= 0 && slot < 5) {
|
||||
def Holster(slot: Int, value: EquipmentSize.Value): EquipmentSize.Value = {
|
||||
if (slot >= 0 && slot < 5) {
|
||||
holsters(slot) = value
|
||||
holsters(slot)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
EquipmentSize.Blocked
|
||||
}
|
||||
}
|
||||
|
||||
def Permissions : List[CertificationType.Value] = permissions
|
||||
def Permissions: List[CertificationType.Value] = permissions
|
||||
|
||||
def Permissions_=(certs : List[CertificationType.Value]) : List[CertificationType.Value] = {
|
||||
def Permissions_=(certs: List[CertificationType.Value]): List[CertificationType.Value] = {
|
||||
permissions = certs
|
||||
Permissions
|
||||
}
|
||||
|
||||
def Use : ExoSuitDefinition = this
|
||||
def Use: ExoSuitDefinition = this
|
||||
|
||||
def canEqual(other: Any): Boolean = other.isInstanceOf[ExoSuitDefinition]
|
||||
|
||||
override def equals(other: Any): Boolean = other match {
|
||||
case that: ExoSuitDefinition =>
|
||||
(that canEqual this) &&
|
||||
suitType == that.suitType
|
||||
case _ => false
|
||||
}
|
||||
override def equals(other: Any): Boolean =
|
||||
other match {
|
||||
case that: ExoSuitDefinition =>
|
||||
(that canEqual this) &&
|
||||
suitType == that.suitType
|
||||
case _ => false
|
||||
}
|
||||
|
||||
override def hashCode(): Int = {
|
||||
val state = Seq(suitType)
|
||||
|
|
@ -126,20 +126,20 @@ class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicD
|
|||
}
|
||||
}
|
||||
|
||||
class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends ExoSuitDefinition(suitType) {
|
||||
class SpecialExoSuitDefinition(private val suitType: ExoSuitType.Value) extends ExoSuitDefinition(suitType) {
|
||||
Name = "heavy_armor"
|
||||
Descriptor = "heavy_armor"
|
||||
|
||||
private var activatedSpecial : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
|
||||
private var activatedSpecial: SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
|
||||
|
||||
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = activatedSpecial
|
||||
def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = activatedSpecial
|
||||
|
||||
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
|
||||
def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
|
||||
activatedSpecial = state
|
||||
UsingSpecial
|
||||
}
|
||||
|
||||
override def Use : ExoSuitDefinition = {
|
||||
override def Use: ExoSuitDefinition = {
|
||||
val obj = new SpecialExoSuitDefinition(SuitType)
|
||||
obj.Permissions = Permissions
|
||||
obj.MaxArmor = MaxArmor
|
||||
|
|
@ -165,24 +165,19 @@ class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends
|
|||
}
|
||||
|
||||
object SpecialExoSuitDefinition {
|
||||
def apply(suitType : ExoSuitType.Value) : SpecialExoSuitDefinition = {
|
||||
def apply(suitType: ExoSuitType.Value): SpecialExoSuitDefinition = {
|
||||
new SpecialExoSuitDefinition(suitType)
|
||||
}
|
||||
|
||||
object Mode extends Enumeration {
|
||||
type Type = Value
|
||||
|
||||
val
|
||||
Normal,
|
||||
Anchored,
|
||||
Overdrive,
|
||||
Shielded
|
||||
= Value
|
||||
val Normal, Anchored, Overdrive, Shielded = Value
|
||||
}
|
||||
}
|
||||
|
||||
object ExoSuitDefinition {
|
||||
def apply(suitType : ExoSuitType.Value) : ExoSuitDefinition = {
|
||||
def apply(suitType: ExoSuitType.Value): ExoSuitDefinition = {
|
||||
new ExoSuitDefinition(suitType)
|
||||
}
|
||||
|
||||
|
|
@ -192,16 +187,17 @@ object ExoSuitDefinition {
|
|||
* @param faction the faction the player belongs to for this exosuit
|
||||
* @return the exo-suit definition
|
||||
*/
|
||||
def Select(suit : ExoSuitType.Value, faction : PlanetSideEmpire.Value) : ExoSuitDefinition = {
|
||||
def Select(suit: ExoSuitType.Value, faction: PlanetSideEmpire.Value): ExoSuitDefinition = {
|
||||
suit match {
|
||||
case ExoSuitType.Infiltration => GlobalDefinitions.Infiltration.Use
|
||||
case ExoSuitType.Agile => GlobalDefinitions.Agile.Use
|
||||
case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use
|
||||
case ExoSuitType.MAX => faction match {
|
||||
case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use
|
||||
case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use
|
||||
case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use
|
||||
}
|
||||
case ExoSuitType.Agile => GlobalDefinitions.Agile.Use
|
||||
case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use
|
||||
case ExoSuitType.MAX =>
|
||||
faction match {
|
||||
case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use
|
||||
case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use
|
||||
case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use
|
||||
}
|
||||
case _ => GlobalDefinitions.Standard.Use
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,16 +17,20 @@ import scala.collection.mutable
|
|||
* @param implantType the type of implant that is defined
|
||||
* @see `ImplantType`
|
||||
*/
|
||||
class ImplantDefinition(private val implantType : Int) extends BasicDefinition {
|
||||
class ImplantDefinition(private val implantType: Int) extends BasicDefinition {
|
||||
ImplantType(implantType)
|
||||
|
||||
/** how long it takes the implant to become ready for activation; is milliseconds */
|
||||
private var initializationDuration : Long = 0L
|
||||
private var initializationDuration: Long = 0L
|
||||
|
||||
/** a passive certification is activated as soon as it is ready (or other condition) */
|
||||
private var passive : Boolean = false
|
||||
private var passive: Boolean = false
|
||||
|
||||
/** how much turning on the implant costs */
|
||||
private var activationStaminaCost : Int = 0
|
||||
private var activationStaminaCost: Int = 0
|
||||
|
||||
/** how much energy does this implant cost to remain activate per interval tick */
|
||||
private var staminaCost : Int = 0
|
||||
private var staminaCost: Int = 0
|
||||
|
||||
/**
|
||||
* How often in milliseconds the stamina cost will be applied, per exo-suit type
|
||||
|
|
@ -37,59 +41,59 @@ class ImplantDefinition(private val implantType : Int) extends BasicDefinition {
|
|||
* stamina_consumption_interval3 = Rexo
|
||||
* stamina_consumption_interval4 = MAX?
|
||||
*/
|
||||
private var costIntervalDefault : Int = 0
|
||||
private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault)
|
||||
private var costIntervalDefault: Int = 0
|
||||
private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault)
|
||||
Name = "implant"
|
||||
|
||||
def InitializationDuration : Long = initializationDuration
|
||||
def InitializationDuration: Long = initializationDuration
|
||||
|
||||
def InitializationDuration_=(time : Long) : Long = {
|
||||
def InitializationDuration_=(time: Long): Long = {
|
||||
initializationDuration = math.max(0, time)
|
||||
InitializationDuration
|
||||
}
|
||||
|
||||
def Passive : Boolean = passive
|
||||
def Passive: Boolean = passive
|
||||
|
||||
def Passive_=(isPassive : Boolean) : Boolean = {
|
||||
def Passive_=(isPassive: Boolean): Boolean = {
|
||||
passive = isPassive
|
||||
Passive
|
||||
}
|
||||
|
||||
def ActivationStaminaCost : Int = activationStaminaCost
|
||||
def ActivationStaminaCost: Int = activationStaminaCost
|
||||
|
||||
def ActivationStaminaCost_=(charge : Int) : Int = {
|
||||
def ActivationStaminaCost_=(charge: Int): Int = {
|
||||
activationStaminaCost = math.max(0, charge)
|
||||
ActivationStaminaCost
|
||||
}
|
||||
|
||||
def StaminaCost : Int = staminaCost
|
||||
def StaminaCost: Int = staminaCost
|
||||
|
||||
def StaminaCost_=(charge : Int) : Int = {
|
||||
def StaminaCost_=(charge: Int): Int = {
|
||||
staminaCost = math.max(0, charge)
|
||||
StaminaCost
|
||||
}
|
||||
|
||||
|
||||
def CostIntervalDefault : Int = {
|
||||
def CostIntervalDefault: Int = {
|
||||
costIntervalDefault
|
||||
}
|
||||
def CostIntervalDefault_=(interval : Int) : Int = {
|
||||
def CostIntervalDefault_=(interval: Int): Int = {
|
||||
costIntervalDefault = interval
|
||||
CostIntervalDefault
|
||||
}
|
||||
|
||||
def GetCostIntervalByExoSuit(exosuit : ExoSuitType.Value) : Int = costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault)
|
||||
def CostIntervalByExoSuitHashMap : mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit
|
||||
def GetCostIntervalByExoSuit(exosuit: ExoSuitType.Value): Int =
|
||||
costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault)
|
||||
def CostIntervalByExoSuitHashMap: mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit
|
||||
|
||||
def Type : ImplantType.Value = ImplantType(implantType)
|
||||
def Type: ImplantType.Value = ImplantType(implantType)
|
||||
}
|
||||
|
||||
object ImplantDefinition {
|
||||
def apply(implantType : Int) : ImplantDefinition = {
|
||||
def apply(implantType: Int): ImplantDefinition = {
|
||||
new ImplantDefinition(implantType)
|
||||
}
|
||||
|
||||
def apply(implantType : ImplantType.Value) : ImplantDefinition = {
|
||||
def apply(implantType: ImplantType.Value): ImplantDefinition = {
|
||||
new ImplantDefinition(implantType.id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.objects.equipment.Kits
|
|||
* The definition for a personal one-time-use recovery item.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||
class KitDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
import net.psforever.objects.inventory.InventoryTile
|
||||
Kits(objectId) //let throw NoSuchElementException
|
||||
|
|
@ -21,11 +21,11 @@ class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
|||
object KitDefinition {
|
||||
private val converter = new KitConverter()
|
||||
|
||||
def apply(objectId: Int) : KitDefinition = {
|
||||
def apply(objectId: Int): KitDefinition = {
|
||||
new KitDefinition(objectId)
|
||||
}
|
||||
|
||||
def apply(kit : Kits.Value) : KitDefinition = {
|
||||
def apply(kit: Kits.Value): KitDefinition = {
|
||||
new KitDefinition(kit.id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,26 +17,28 @@ import net.psforever.objects.definition.converter.{ObjectCreateConverter, Packet
|
|||
* So long as it is an `ObjectCreatePacket`, those methods can be called correctly for a game object of the desired type.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
abstract class ObjectDefinition(private val objectId : Int) extends BasicDefinition {
|
||||
abstract class ObjectDefinition(private val objectId: Int) extends BasicDefinition {
|
||||
|
||||
/** a data converter for this type of object */
|
||||
protected var packet : PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() { }
|
||||
protected var packet: PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() {}
|
||||
Name = "object definition"
|
||||
|
||||
/**
|
||||
* Get the conversion object.
|
||||
* @return
|
||||
*/
|
||||
final def Packet : ObjectCreateConverter[PlanetSideGameObject] = packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]]
|
||||
final def Packet: ObjectCreateConverter[PlanetSideGameObject] =
|
||||
packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]]
|
||||
|
||||
/**
|
||||
* Assign this definition a conversion object.
|
||||
* @param pkt the new converter
|
||||
* @return the current converter, after assignment
|
||||
*/
|
||||
final def Packet_=(pkt : ObjectCreateConverter[_]) : PacketConverter = {
|
||||
final def Packet_=(pkt: ObjectCreateConverter[_]): PacketConverter = {
|
||||
packet = pkt
|
||||
Packet
|
||||
}
|
||||
|
||||
def ObjectId : Int = objectId
|
||||
def ObjectId: Int = objectId
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,168 +10,170 @@ import net.psforever.objects.vital.{DamageType, StandardDamageProfile}
|
|||
* `Tool` objects emit `ProjectileDefinition` objects and that is later wrapped into a `Projectile` object.
|
||||
* @param objectId the object's identifier number
|
||||
*/
|
||||
class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||
with JammingUnit
|
||||
with StandardDamageProfile {
|
||||
private val projectileType : Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
||||
private var acceleration : Int = 0
|
||||
private var accelerationUntil : Float = 0f
|
||||
private var damageType : DamageType.Value = DamageType.None
|
||||
private var damageTypeSecondary : DamageType.Value = DamageType.None
|
||||
private var degradeDelay : Float = 1f
|
||||
private var degradeMultiplier : Float = 1f
|
||||
private var initialVelocity : Int = 1
|
||||
private var lifespan : Float = 1f
|
||||
private var damageAtEdge : Float = 1f
|
||||
private var damageRadius : Float = 1f
|
||||
private var useDamage1Subtract : Boolean = false
|
||||
private var existsOnRemoteClients : Boolean = false //`true` spawns a server-managed object
|
||||
private var remoteClientData : (Int, Int) = (0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
|
||||
private var autoLock : Boolean = false
|
||||
private var additionalEffect : Boolean = false
|
||||
private var jammerProjectile : Boolean = false
|
||||
class ProjectileDefinition(objectId: Int)
|
||||
extends ObjectDefinition(objectId)
|
||||
with JammingUnit
|
||||
with StandardDamageProfile {
|
||||
private val projectileType: Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
|
||||
private var acceleration: Int = 0
|
||||
private var accelerationUntil: Float = 0f
|
||||
private var damageType: DamageType.Value = DamageType.None
|
||||
private var damageTypeSecondary: DamageType.Value = DamageType.None
|
||||
private var degradeDelay: Float = 1f
|
||||
private var degradeMultiplier: Float = 1f
|
||||
private var initialVelocity: Int = 1
|
||||
private var lifespan: Float = 1f
|
||||
private var damageAtEdge: Float = 1f
|
||||
private var damageRadius: Float = 1f
|
||||
private var useDamage1Subtract: Boolean = false
|
||||
private var existsOnRemoteClients: Boolean = false //`true` spawns a server-managed object
|
||||
private var remoteClientData: (Int, Int) =
|
||||
(0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
|
||||
private var autoLock: Boolean = false
|
||||
private var additionalEffect: Boolean = false
|
||||
private var jammerProjectile: Boolean = false
|
||||
//derived calculations
|
||||
private var distanceMax : Float = 0f
|
||||
private var distanceFromAcceleration : Float = 0f
|
||||
private var distanceNoDegrade : Float = 0f
|
||||
private var finalVelocity : Float = 0f
|
||||
private var distanceMax: Float = 0f
|
||||
private var distanceFromAcceleration: Float = 0f
|
||||
private var distanceNoDegrade: Float = 0f
|
||||
private var finalVelocity: Float = 0f
|
||||
Name = "projectile"
|
||||
|
||||
def ProjectileType : Projectiles.Value = projectileType
|
||||
def ProjectileType: Projectiles.Value = projectileType
|
||||
|
||||
def UseDamage1Subtract : Boolean = useDamage1Subtract
|
||||
def UseDamage1Subtract: Boolean = useDamage1Subtract
|
||||
|
||||
def UseDamage1Subtract_=(useDamage1Subtract : Boolean) : Boolean = {
|
||||
def UseDamage1Subtract_=(useDamage1Subtract: Boolean): Boolean = {
|
||||
this.useDamage1Subtract = useDamage1Subtract
|
||||
UseDamage1Subtract
|
||||
}
|
||||
|
||||
def Acceleration : Int = acceleration
|
||||
def Acceleration: Int = acceleration
|
||||
|
||||
def Acceleration_=(accel : Int) : Int = {
|
||||
def Acceleration_=(accel: Int): Int = {
|
||||
acceleration = accel
|
||||
Acceleration
|
||||
}
|
||||
|
||||
def AccelerationUntil : Float = accelerationUntil
|
||||
def AccelerationUntil: Float = accelerationUntil
|
||||
|
||||
def AccelerationUntil_=(accelUntil : Float) : Float = {
|
||||
def AccelerationUntil_=(accelUntil: Float): Float = {
|
||||
accelerationUntil = accelUntil
|
||||
AccelerationUntil
|
||||
}
|
||||
|
||||
def ProjectileDamageType : DamageType.Value = damageType
|
||||
def ProjectileDamageType: DamageType.Value = damageType
|
||||
|
||||
def ProjectileDamageType_=(damageType1 : DamageType.Value) : DamageType.Value = {
|
||||
def ProjectileDamageType_=(damageType1: DamageType.Value): DamageType.Value = {
|
||||
damageType = damageType1
|
||||
ProjectileDamageType
|
||||
}
|
||||
|
||||
def ProjectileDamageTypeSecondary : DamageType.Value = damageTypeSecondary
|
||||
def ProjectileDamageTypeSecondary: DamageType.Value = damageTypeSecondary
|
||||
|
||||
def ProjectileDamageTypeSecondary_=(damageTypeSecondary1 : DamageType.Value) : DamageType.Value = {
|
||||
def ProjectileDamageTypeSecondary_=(damageTypeSecondary1: DamageType.Value): DamageType.Value = {
|
||||
damageTypeSecondary = damageTypeSecondary1
|
||||
ProjectileDamageTypeSecondary
|
||||
}
|
||||
|
||||
def DegradeDelay : Float = degradeDelay
|
||||
def DegradeDelay: Float = degradeDelay
|
||||
|
||||
def DegradeDelay_=(degradeDelay : Float) : Float = {
|
||||
def DegradeDelay_=(degradeDelay: Float): Float = {
|
||||
this.degradeDelay = degradeDelay
|
||||
DegradeDelay
|
||||
}
|
||||
|
||||
def DegradeMultiplier : Float = degradeMultiplier
|
||||
def DegradeMultiplier: Float = degradeMultiplier
|
||||
|
||||
def DegradeMultiplier_=(degradeMultiplier : Float) : Float = {
|
||||
def DegradeMultiplier_=(degradeMultiplier: Float): Float = {
|
||||
this.degradeMultiplier = degradeMultiplier
|
||||
DegradeMultiplier
|
||||
}
|
||||
|
||||
def InitialVelocity : Int = initialVelocity
|
||||
def InitialVelocity: Int = initialVelocity
|
||||
|
||||
def InitialVelocity_=(initialVelocity : Int) : Int = {
|
||||
def InitialVelocity_=(initialVelocity: Int): Int = {
|
||||
this.initialVelocity = initialVelocity
|
||||
InitialVelocity
|
||||
}
|
||||
|
||||
def Lifespan : Float = lifespan
|
||||
def Lifespan: Float = lifespan
|
||||
|
||||
def Lifespan_=(lifespan : Float) : Float = {
|
||||
def Lifespan_=(lifespan: Float): Float = {
|
||||
this.lifespan = lifespan
|
||||
Lifespan
|
||||
}
|
||||
|
||||
def DamageAtEdge : Float = damageAtEdge
|
||||
def DamageAtEdge: Float = damageAtEdge
|
||||
|
||||
def DamageAtEdge_=(damageAtEdge : Float) : Float = {
|
||||
def DamageAtEdge_=(damageAtEdge: Float): Float = {
|
||||
this.damageAtEdge = damageAtEdge
|
||||
DamageAtEdge
|
||||
}
|
||||
|
||||
def DamageRadius : Float = damageRadius
|
||||
def DamageRadius: Float = damageRadius
|
||||
|
||||
def DamageRadius_=(damageRadius : Float) : Float = {
|
||||
def DamageRadius_=(damageRadius: Float): Float = {
|
||||
this.damageRadius = damageRadius
|
||||
DamageRadius
|
||||
}
|
||||
|
||||
def ExistsOnRemoteClients : Boolean = existsOnRemoteClients
|
||||
def ExistsOnRemoteClients: Boolean = existsOnRemoteClients
|
||||
|
||||
def ExistsOnRemoteClients_=(existsOnRemoteClients : Boolean) : Boolean = {
|
||||
def ExistsOnRemoteClients_=(existsOnRemoteClients: Boolean): Boolean = {
|
||||
this.existsOnRemoteClients = existsOnRemoteClients
|
||||
ExistsOnRemoteClients
|
||||
}
|
||||
|
||||
def RemoteClientData : (Int, Int) = remoteClientData
|
||||
def RemoteClientData: (Int, Int) = remoteClientData
|
||||
|
||||
def RemoteClientData_=(remoteClientData : (Int, Int)) : (Int, Int) = {
|
||||
def RemoteClientData_=(remoteClientData: (Int, Int)): (Int, Int) = {
|
||||
this.remoteClientData = remoteClientData
|
||||
RemoteClientData
|
||||
}
|
||||
|
||||
def AutoLock : Boolean = autoLock
|
||||
def AutoLock: Boolean = autoLock
|
||||
|
||||
def AutoLock_=(lockState : Boolean) : Boolean = {
|
||||
def AutoLock_=(lockState: Boolean): Boolean = {
|
||||
autoLock = lockState
|
||||
AutoLock
|
||||
}
|
||||
|
||||
def AdditionalEffect : Boolean = additionalEffect
|
||||
def AdditionalEffect: Boolean = additionalEffect
|
||||
|
||||
def AdditionalEffect_=(effect : Boolean) : Boolean = {
|
||||
def AdditionalEffect_=(effect: Boolean): Boolean = {
|
||||
additionalEffect = effect
|
||||
AdditionalEffect
|
||||
}
|
||||
|
||||
def JammerProjectile : Boolean = jammerProjectile
|
||||
def JammerProjectile: Boolean = jammerProjectile
|
||||
|
||||
def JammerProjectile_=(effect : Boolean) : Boolean = {
|
||||
def JammerProjectile_=(effect: Boolean): Boolean = {
|
||||
jammerProjectile = effect
|
||||
JammerProjectile
|
||||
}
|
||||
|
||||
def DistanceMax : Float = distanceMax //accessor only
|
||||
def DistanceMax: Float = distanceMax //accessor only
|
||||
|
||||
def DistanceFromAcceleration : Float = distanceFromAcceleration //accessor only
|
||||
def DistanceFromAcceleration: Float = distanceFromAcceleration //accessor only
|
||||
|
||||
def DistanceNoDegrade : Float = distanceNoDegrade //accessor only
|
||||
def DistanceNoDegrade: Float = distanceNoDegrade //accessor only
|
||||
|
||||
def FinalVelocity : Float = finalVelocity //accessor only
|
||||
def FinalVelocity: Float = finalVelocity //accessor only
|
||||
}
|
||||
|
||||
object ProjectileDefinition {
|
||||
def apply(projectileType : Projectiles.Value) : ProjectileDefinition = {
|
||||
def apply(projectileType: Projectiles.Value): ProjectileDefinition = {
|
||||
new ProjectileDefinition(projectileType.id)
|
||||
}
|
||||
|
||||
def CalculateDerivedFields(pdef : ProjectileDefinition) : Unit = {
|
||||
val (distanceMax, distanceFromAcceleration, finalVelocity) : (Float, Float, Float) = if(pdef.Acceleration == 0) {
|
||||
def CalculateDerivedFields(pdef: ProjectileDefinition): Unit = {
|
||||
val (distanceMax, distanceFromAcceleration, finalVelocity): (Float, Float, Float) = if (pdef.Acceleration == 0) {
|
||||
(pdef.InitialVelocity * pdef.Lifespan, 0, pdef.InitialVelocity.toFloat)
|
||||
}
|
||||
else {
|
||||
val distanceFromAcceleration = (pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil)
|
||||
val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil
|
||||
} else {
|
||||
val distanceFromAcceleration =
|
||||
(pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil)
|
||||
val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil
|
||||
val distanceAfterAcceleration = finalVelocity * (pdef.Lifespan - pdef.AccelerationUntil)
|
||||
(distanceFromAcceleration + distanceAfterAcceleration, distanceFromAcceleration, finalVelocity)
|
||||
}
|
||||
|
|
@ -179,13 +181,11 @@ object ProjectileDefinition {
|
|||
pdef.distanceFromAcceleration = distanceFromAcceleration
|
||||
pdef.finalVelocity = finalVelocity
|
||||
|
||||
pdef.distanceNoDegrade = if(pdef.DegradeDelay == 0f) {
|
||||
pdef.distanceNoDegrade = if (pdef.DegradeDelay == 0f) {
|
||||
pdef.distanceMax
|
||||
}
|
||||
else if(pdef.DegradeDelay < pdef.AccelerationUntil) {
|
||||
} else if (pdef.DegradeDelay < pdef.AccelerationUntil) {
|
||||
(pdef.DegradeDelay * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.DegradeDelay * pdef.DegradeDelay)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pdef.distanceFromAcceleration + pdef.finalVelocity * (pdef.DegradeDelay - pdef.AccelerationUntil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,41 +7,44 @@ import net.psforever.objects.vehicles.SeatArmorRestriction
|
|||
* The definition for a seat.
|
||||
*/
|
||||
class SeatDefinition extends BasicDefinition {
|
||||
|
||||
/** a restriction on the type of exo-suit a person can wear */
|
||||
private var armorRestriction : SeatArmorRestriction.Value = SeatArmorRestriction.NoMax
|
||||
private var armorRestriction: SeatArmorRestriction.Value = SeatArmorRestriction.NoMax
|
||||
|
||||
/** the user can escape while the vehicle is moving */
|
||||
private var bailable : Boolean = false
|
||||
private var bailable: Boolean = false
|
||||
|
||||
/** any controlled weapon */
|
||||
private var weaponMount : Option[Int] = None
|
||||
private var weaponMount: Option[Int] = None
|
||||
Name = "seat"
|
||||
|
||||
def ArmorRestriction : SeatArmorRestriction.Value = {
|
||||
def ArmorRestriction: SeatArmorRestriction.Value = {
|
||||
this.armorRestriction
|
||||
}
|
||||
|
||||
def ArmorRestriction_=(restriction : SeatArmorRestriction.Value) : SeatArmorRestriction.Value = {
|
||||
def ArmorRestriction_=(restriction: SeatArmorRestriction.Value): SeatArmorRestriction.Value = {
|
||||
this.armorRestriction = restriction
|
||||
restriction
|
||||
}
|
||||
|
||||
def Bailable : Boolean = {
|
||||
def Bailable: Boolean = {
|
||||
this.bailable
|
||||
}
|
||||
|
||||
def Bailable_=(canBail : Boolean) : Boolean = {
|
||||
def Bailable_=(canBail: Boolean): Boolean = {
|
||||
this.bailable = canBail
|
||||
canBail
|
||||
}
|
||||
|
||||
def ControlledWeapon : Option[Int] = {
|
||||
def ControlledWeapon: Option[Int] = {
|
||||
this.weaponMount
|
||||
}
|
||||
|
||||
def ControlledWeapon_=(wep : Int) : Option[Int] = {
|
||||
def ControlledWeapon_=(wep: Int): Option[Int] = {
|
||||
ControlledWeapon_=(Some(wep))
|
||||
}
|
||||
|
||||
def ControlledWeapon_=(wep : Option[Int]) : Option[Int] = {
|
||||
def ControlledWeapon_=(wep: Option[Int]): Option[Int] = {
|
||||
this.weaponMount = wep
|
||||
ControlledWeapon
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,66 +7,72 @@ import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
|
|||
import net.psforever.objects.definition.converter.SmallDeployableConverter
|
||||
import net.psforever.objects.serverobject.PlanetSideServerObject
|
||||
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
|
||||
import net.psforever.objects.vital.{DamageResistanceModel, NoResistanceSelection, StandardDeployableDamage, VitalityDefinition}
|
||||
import net.psforever.objects.vital.{
|
||||
DamageResistanceModel,
|
||||
NoResistanceSelection,
|
||||
StandardDeployableDamage,
|
||||
VitalityDefinition
|
||||
}
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
trait BaseDeployableDefinition {
|
||||
private var category : DeployableCategory.Value = DeployableCategory.Boomers
|
||||
private var deployTime : Long = (1 second).toMillis //ms
|
||||
private var category: DeployableCategory.Value = DeployableCategory.Boomers
|
||||
private var deployTime: Long = (1 second).toMillis //ms
|
||||
|
||||
def Item : DeployedItem.Value
|
||||
def Item: DeployedItem.Value
|
||||
|
||||
def DeployCategory : DeployableCategory.Value = category
|
||||
def DeployCategory: DeployableCategory.Value = category
|
||||
|
||||
def DeployCategory_=(cat : DeployableCategory.Value) : DeployableCategory.Value = {
|
||||
def DeployCategory_=(cat: DeployableCategory.Value): DeployableCategory.Value = {
|
||||
category = cat
|
||||
DeployCategory
|
||||
}
|
||||
|
||||
def DeployTime : Long = deployTime
|
||||
def DeployTime: Long = deployTime
|
||||
|
||||
def DeployTime_=(time : FiniteDuration) : Long = DeployTime_=(time.toMillis)
|
||||
def DeployTime_=(time: FiniteDuration): Long = DeployTime_=(time.toMillis)
|
||||
|
||||
def DeployTime_=(time: Long) : Long = {
|
||||
def DeployTime_=(time: Long): Long = {
|
||||
deployTime = time
|
||||
DeployTime
|
||||
}
|
||||
|
||||
def Initialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { }
|
||||
def Initialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
|
||||
|
||||
def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { }
|
||||
def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
|
||||
|
||||
def Uninitialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { }
|
||||
def Uninitialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
|
||||
|
||||
def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { }
|
||||
def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
|
||||
}
|
||||
|
||||
abstract class DeployableDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||
with DamageResistanceModel
|
||||
with ResistanceProfileMutators
|
||||
with VitalityDefinition
|
||||
with BaseDeployableDefinition {
|
||||
abstract class DeployableDefinition(objectId: Int)
|
||||
extends ObjectDefinition(objectId)
|
||||
with DamageResistanceModel
|
||||
with ResistanceProfileMutators
|
||||
with VitalityDefinition
|
||||
with BaseDeployableDefinition {
|
||||
private val item = DeployedItem(objectId) //let throw NoSuchElementException
|
||||
DamageUsing = StandardDeployableDamage
|
||||
ResistUsing = NoResistanceSelection
|
||||
|
||||
def Item : DeployedItem.Value = item
|
||||
def Item: DeployedItem.Value = item
|
||||
}
|
||||
|
||||
class SimpleDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId) {
|
||||
class SimpleDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId) {
|
||||
Packet = new SmallDeployableConverter
|
||||
}
|
||||
|
||||
abstract class ComplexDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId)
|
||||
abstract class ComplexDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId)
|
||||
|
||||
object SimpleDeployableDefinition {
|
||||
def apply(item : DeployedItem.Value) : SimpleDeployableDefinition =
|
||||
def apply(item: DeployedItem.Value): SimpleDeployableDefinition =
|
||||
new SimpleDeployableDefinition(item.id)
|
||||
|
||||
def SimpleUninitialize(obj : PlanetSideGameObject, context : ActorContext) : Unit = { }
|
||||
def SimpleUninitialize(obj: PlanetSideGameObject, context: ActorContext): Unit = {}
|
||||
|
||||
def SimpleUninitialize(obj : PlanetSideServerObject, context : ActorContext) : Unit = {
|
||||
def SimpleUninitialize(obj: PlanetSideServerObject, context: ActorContext): Unit = {
|
||||
context.stop(obj.Actor)
|
||||
obj.Actor = Default.Actor
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package net.psforever.objects.definition
|
|||
|
||||
import net.psforever.objects.equipment.SItem
|
||||
|
||||
class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||
class SimpleItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
|
||||
import net.psforever.objects.equipment.EquipmentSize
|
||||
SItem(objectId) //let throw NoSuchElementException
|
||||
Name = "tool"
|
||||
|
|
@ -11,11 +11,11 @@ class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId)
|
|||
}
|
||||
|
||||
object SimpleItemDefinition {
|
||||
def apply(objectId : Int) : SimpleItemDefinition = {
|
||||
def apply(objectId: Int): SimpleItemDefinition = {
|
||||
new SimpleItemDefinition(objectId)
|
||||
}
|
||||
|
||||
def apply(simpItem : SItem.Value) : SimpleItemDefinition = {
|
||||
def apply(simpItem: SItem.Value): SimpleItemDefinition = {
|
||||
new SimpleItemDefinition(simpItem.id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,27 +6,27 @@ import net.psforever.objects.equipment.FireModeDefinition
|
|||
|
||||
import scala.collection.mutable
|
||||
|
||||
class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
||||
private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
|
||||
private val projectileTypes : mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
|
||||
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
|
||||
private var defaultFireModeIndex : Option[Int] = None
|
||||
class ToolDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
|
||||
private val ammoTypes: mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
|
||||
private val projectileTypes: mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
|
||||
private val fireModes: mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
|
||||
private var defaultFireModeIndex: Option[Int] = None
|
||||
Name = "tool"
|
||||
Packet = ToolDefinition.converter
|
||||
|
||||
def AmmoTypes : mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
|
||||
def AmmoTypes: mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
|
||||
|
||||
def ProjectileTypes : mutable.ListBuffer[ProjectileDefinition] = projectileTypes
|
||||
def ProjectileTypes: mutable.ListBuffer[ProjectileDefinition] = projectileTypes
|
||||
|
||||
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes
|
||||
def FireModes: mutable.ListBuffer[FireModeDefinition] = fireModes
|
||||
|
||||
def NextFireModeIndex(index : Int) : Int = index + 1
|
||||
def NextFireModeIndex(index: Int): Int = index + 1
|
||||
|
||||
def DefaultFireModeIndex : Int = defaultFireModeIndex.getOrElse(0)
|
||||
def DefaultFireModeIndex: Int = defaultFireModeIndex.getOrElse(0)
|
||||
|
||||
def DefaultFireModeIndex_=(index : Int) : Int = DefaultFireModeIndex_=(Some(index))
|
||||
def DefaultFireModeIndex_=(index: Int): Int = DefaultFireModeIndex_=(Some(index))
|
||||
|
||||
def DefaultFireModeIndex_=(index : Option[Int]) : Int = {
|
||||
def DefaultFireModeIndex_=(index: Option[Int]): Int = {
|
||||
defaultFireModeIndex = index
|
||||
DefaultFireModeIndex
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
|
|||
object ToolDefinition {
|
||||
private val converter = new ToolConverter()
|
||||
|
||||
def apply(objectId : Int) : ToolDefinition = {
|
||||
def apply(objectId: Int): ToolDefinition = {
|
||||
new ToolDefinition(objectId)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,37 +15,39 @@ import scala.concurrent.duration._
|
|||
* An object definition system used to construct and retain the parameters of various vehicles.
|
||||
* @param objectId the object id that is associated with this sort of `Vehicle`
|
||||
*/
|
||||
class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
||||
with VitalityDefinition
|
||||
with ResistanceProfileMutators
|
||||
with DamageResistanceModel {
|
||||
/** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */
|
||||
private var maxShields : Int = 0
|
||||
/* key - seat index, value - seat object */
|
||||
private val seats : mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
|
||||
private val cargo : mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
|
||||
/* key - entry point index, value - seat index */
|
||||
private val mountPoints : mutable.HashMap[Int, Int] = mutable.HashMap()
|
||||
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
|
||||
private val weapons : mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
|
||||
private var deployment : Boolean = false
|
||||
private val utilities : mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
|
||||
private val utilityOffsets : mutable.HashMap[Int, Vector3] = mutable.HashMap()
|
||||
private var deploymentTime_Deploy : Int = 0 //ms
|
||||
private var deploymentTime_Undeploy : Int = 0 //ms
|
||||
private var trunkSize : InventoryTile = InventoryTile.None
|
||||
private var trunkOffset : Int = 0
|
||||
class VehicleDefinition(objectId: Int)
|
||||
extends ObjectDefinition(objectId)
|
||||
with VitalityDefinition
|
||||
with ResistanceProfileMutators
|
||||
with DamageResistanceModel {
|
||||
|
||||
/** The position offset of the trunk, orientation as East = 0 */
|
||||
private var trunkLocation : Vector3 = Vector3.Zero
|
||||
private var canCloak : Boolean = false
|
||||
private var canFly : Boolean = false
|
||||
private var canBeOwned : Boolean = true
|
||||
private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0)
|
||||
private var deconTime : Option[FiniteDuration] = None
|
||||
private var maxCapacitor : Int = 0
|
||||
private var maxNtuCapacitor : Int = 0
|
||||
private var destroyedModel : Option[DestroyedVehicle.Value] = None
|
||||
/** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */
|
||||
private var maxShields: Int = 0
|
||||
/* key - seat index, value - seat object */
|
||||
private val seats: mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
|
||||
private val cargo: mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
|
||||
/* key - entry point index, value - seat index */
|
||||
private val mountPoints: mutable.HashMap[Int, Int] = mutable.HashMap()
|
||||
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
|
||||
private val weapons: mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
|
||||
private var deployment: Boolean = false
|
||||
private val utilities: mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
|
||||
private val utilityOffsets: mutable.HashMap[Int, Vector3] = mutable.HashMap()
|
||||
private var deploymentTime_Deploy: Int = 0 //ms
|
||||
private var deploymentTime_Undeploy: Int = 0 //ms
|
||||
private var trunkSize: InventoryTile = InventoryTile.None
|
||||
private var trunkOffset: Int = 0
|
||||
|
||||
/** The position offset of the trunk, orientation as East = 0 */
|
||||
private var trunkLocation: Vector3 = Vector3.Zero
|
||||
private var canCloak: Boolean = false
|
||||
private var canFly: Boolean = false
|
||||
private var canBeOwned: Boolean = true
|
||||
private var serverVehicleOverrideSpeeds: (Int, Int) = (0, 0)
|
||||
private var deconTime: Option[FiniteDuration] = None
|
||||
private var maxCapacitor: Int = 0
|
||||
private var maxNtuCapacitor: Int = 0
|
||||
private var destroyedModel: Option[DestroyedVehicle.Value] = None
|
||||
Name = "vehicle"
|
||||
Packet = VehicleDefinition.converter
|
||||
DamageUsing = StandardVehicleDamage
|
||||
|
|
@ -54,135 +56,135 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
|||
RepairDistance = 10
|
||||
RepairRestoresAt = 1
|
||||
|
||||
def MaxShields : Int = maxShields
|
||||
def MaxShields: Int = maxShields
|
||||
|
||||
def MaxShields_=(shields : Int) : Int = {
|
||||
def MaxShields_=(shields: Int): Int = {
|
||||
maxShields = shields
|
||||
MaxShields
|
||||
}
|
||||
|
||||
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
|
||||
def Seats: mutable.HashMap[Int, SeatDefinition] = seats
|
||||
|
||||
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo
|
||||
def Cargo: mutable.HashMap[Int, CargoDefinition] = cargo
|
||||
|
||||
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
|
||||
def MountPoints: mutable.HashMap[Int, Int] = mountPoints
|
||||
|
||||
def CanBeOwned : Boolean = canBeOwned
|
||||
def CanBeOwned: Boolean = canBeOwned
|
||||
|
||||
def CanBeOwned_=(ownable : Boolean) : Boolean = {
|
||||
def CanBeOwned_=(ownable: Boolean): Boolean = {
|
||||
canBeOwned = ownable
|
||||
CanBeOwned
|
||||
}
|
||||
|
||||
def CanCloak : Boolean = canCloak
|
||||
def CanCloak: Boolean = canCloak
|
||||
|
||||
def CanCloak_=(cloakable : Boolean) : Boolean = {
|
||||
def CanCloak_=(cloakable: Boolean): Boolean = {
|
||||
canCloak = cloakable
|
||||
CanCloak
|
||||
}
|
||||
|
||||
def CanFly : Boolean = canFly
|
||||
def CanFly: Boolean = canFly
|
||||
|
||||
def CanFly_=(flying : Boolean) : Boolean = {
|
||||
def CanFly_=(flying: Boolean): Boolean = {
|
||||
canFly = flying
|
||||
CanFly
|
||||
}
|
||||
|
||||
def Weapons : mutable.HashMap[Int, ToolDefinition] = weapons
|
||||
def Weapons: mutable.HashMap[Int, ToolDefinition] = weapons
|
||||
|
||||
def Deployment : Boolean = deployment
|
||||
def Deployment: Boolean = deployment
|
||||
|
||||
def Deployment_=(deployable : Boolean) : Boolean = {
|
||||
def Deployment_=(deployable: Boolean): Boolean = {
|
||||
deployment = deployable
|
||||
Deployment
|
||||
}
|
||||
|
||||
def Utilities : mutable.HashMap[Int, UtilityType.Value] = utilities
|
||||
def Utilities: mutable.HashMap[Int, UtilityType.Value] = utilities
|
||||
|
||||
def UtilityOffset : mutable.HashMap[Int, Vector3] = utilityOffsets
|
||||
def UtilityOffset: mutable.HashMap[Int, Vector3] = utilityOffsets
|
||||
|
||||
def DeployTime : Int = deploymentTime_Deploy
|
||||
def DeployTime: Int = deploymentTime_Deploy
|
||||
|
||||
def DeployTime_=(dtime : Int) : Int = {
|
||||
def DeployTime_=(dtime: Int): Int = {
|
||||
deploymentTime_Deploy = dtime
|
||||
DeployTime
|
||||
}
|
||||
|
||||
def DeconstructionTime : Option[FiniteDuration] = deconTime
|
||||
def DeconstructionTime: Option[FiniteDuration] = deconTime
|
||||
|
||||
def DeconstructionTime_=(time : FiniteDuration) : Option[FiniteDuration] = {
|
||||
def DeconstructionTime_=(time: FiniteDuration): Option[FiniteDuration] = {
|
||||
deconTime_=(Some(time))
|
||||
DeconstructionTime
|
||||
}
|
||||
|
||||
def DeconstructionTime_=(time : Option[FiniteDuration]) : Option[FiniteDuration] = {
|
||||
def DeconstructionTime_=(time: Option[FiniteDuration]): Option[FiniteDuration] = {
|
||||
deconTime = time
|
||||
DeconstructionTime
|
||||
}
|
||||
|
||||
def UndeployTime : Int = deploymentTime_Undeploy
|
||||
def UndeployTime: Int = deploymentTime_Undeploy
|
||||
|
||||
def UndeployTime_=(dtime : Int) : Int = {
|
||||
def UndeployTime_=(dtime: Int): Int = {
|
||||
deploymentTime_Undeploy = dtime
|
||||
UndeployTime
|
||||
}
|
||||
|
||||
def TrunkSize : InventoryTile = trunkSize
|
||||
def TrunkSize: InventoryTile = trunkSize
|
||||
|
||||
def TrunkSize_=(tile : InventoryTile) : InventoryTile = {
|
||||
def TrunkSize_=(tile: InventoryTile): InventoryTile = {
|
||||
trunkSize = tile
|
||||
TrunkSize
|
||||
}
|
||||
|
||||
def TrunkOffset : Int = trunkOffset
|
||||
def TrunkOffset: Int = trunkOffset
|
||||
|
||||
def TrunkOffset_=(offset : Int) : Int = {
|
||||
def TrunkOffset_=(offset: Int): Int = {
|
||||
trunkOffset = offset
|
||||
TrunkOffset
|
||||
}
|
||||
|
||||
def TrunkLocation : Vector3 = trunkLocation
|
||||
def TrunkLocation: Vector3 = trunkLocation
|
||||
|
||||
def TrunkLocation_=(location : Vector3) : Vector3 = {
|
||||
def TrunkLocation_=(location: Vector3): Vector3 = {
|
||||
trunkLocation = location
|
||||
TrunkLocation
|
||||
}
|
||||
|
||||
def AutoPilotSpeeds : (Int, Int) = serverVehicleOverrideSpeeds
|
||||
def AutoPilotSpeeds: (Int, Int) = serverVehicleOverrideSpeeds
|
||||
|
||||
def AutoPilotSpeeds_=(speeds : (Int, Int)) : (Int, Int) = {
|
||||
def AutoPilotSpeeds_=(speeds: (Int, Int)): (Int, Int) = {
|
||||
serverVehicleOverrideSpeeds = speeds
|
||||
AutoPilotSpeeds
|
||||
}
|
||||
|
||||
def AutoPilotSpeed1 : Int = serverVehicleOverrideSpeeds._1
|
||||
def AutoPilotSpeed1: Int = serverVehicleOverrideSpeeds._1
|
||||
|
||||
def AutoPilotSpeed2 : Int = serverVehicleOverrideSpeeds._2
|
||||
def AutoPilotSpeed2: Int = serverVehicleOverrideSpeeds._2
|
||||
|
||||
def MaxNtuCapacitor : Int = maxNtuCapacitor
|
||||
def MaxNtuCapacitor: Int = maxNtuCapacitor
|
||||
|
||||
def MaxNtuCapacitor_=(max: Int) : Int = {
|
||||
def MaxNtuCapacitor_=(max: Int): Int = {
|
||||
maxNtuCapacitor = max
|
||||
MaxNtuCapacitor
|
||||
}
|
||||
|
||||
def MaxCapacitor : Int = maxCapacitor
|
||||
def MaxCapacitor: Int = maxCapacitor
|
||||
|
||||
def MaxCapacitor_=(max: Int) : Int = {
|
||||
def MaxCapacitor_=(max: Int): Int = {
|
||||
maxCapacitor = max
|
||||
MaxCapacitor
|
||||
}
|
||||
|
||||
private var jackDuration = Array(0, 0, 0, 0)
|
||||
private var jackDuration = Array(0, 0, 0, 0)
|
||||
def JackingDuration: Array[Int] = jackDuration
|
||||
def JackingDuration_=(arr: Array[Int]) : Array[Int] = {
|
||||
def JackingDuration_=(arr: Array[Int]): Array[Int] = {
|
||||
jackDuration = arr
|
||||
arr
|
||||
}
|
||||
|
||||
def DestroyedModel : Option[DestroyedVehicle.Value] = destroyedModel
|
||||
def DestroyedModel: Option[DestroyedVehicle.Value] = destroyedModel
|
||||
|
||||
def DestroyedModel_=(model : Option[DestroyedVehicle.Value]) : Option[DestroyedVehicle.Value] = {
|
||||
def DestroyedModel_=(model: Option[DestroyedVehicle.Value]): Option[DestroyedVehicle.Value] = {
|
||||
destroyedModel = model
|
||||
DestroyedModel
|
||||
}
|
||||
|
|
@ -191,7 +193,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
|
|||
object VehicleDefinition {
|
||||
private val converter = new VehicleConverter
|
||||
|
||||
def apply(objectId: Int) : VehicleDefinition = {
|
||||
def apply(objectId: Int): VehicleDefinition = {
|
||||
new VehicleDefinition(objectId)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import net.psforever.types.PlanetSideGUID
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
|
||||
override def ConstructorData(obj : ConstructionItem) : Try[HandheldData] = {
|
||||
override def ConstructorData(obj: ConstructionItem): Try[HandheldData] = {
|
||||
Success(
|
||||
HandheldData(
|
||||
CommonFieldData(
|
||||
|
|
@ -27,7 +27,7 @@ class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
|
|||
)
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : ConstructionItem) : Try[DetailedConstructionToolData] = {
|
||||
override def DetailedConstructorData(obj: ConstructionItem): Try[DetailedConstructionToolData] = {
|
||||
Success(
|
||||
DetailedConstructionToolData(
|
||||
CommonFieldData(
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class AmmoBoxConverter extends ObjectCreateConverter[AmmoBox] {
|
||||
override def ConstructorData(obj : AmmoBox) : Try[CommonFieldData] = {
|
||||
override def ConstructorData(obj: AmmoBox): Try[CommonFieldData] = {
|
||||
Success(CommonFieldData()(false))
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : AmmoBox) : Try[DetailedAmmoBoxData] = {
|
||||
override def DetailedConstructorData(obj: AmmoBox): Try[DetailedAmmoBoxData] = {
|
||||
Success(
|
||||
DetailedAmmoBoxData(
|
||||
CommonFieldData(
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import scala.annotation.tailrec
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class AvatarConverter extends ObjectCreateConverter[Player]() {
|
||||
override def ConstructorData(obj : Player) : Try[PlayerData] = {
|
||||
override def ConstructorData(obj: Player): Try[PlayerData] = {
|
||||
import AvatarConverter._
|
||||
Success(
|
||||
if(obj.VehicleSeated.isEmpty) {
|
||||
if (obj.VehicleSeated.isEmpty) {
|
||||
PlayerData(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
MakeAppearanceData(obj),
|
||||
|
|
@ -21,8 +21,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
|
|||
MakeInventoryData(obj),
|
||||
GetDrawnSlot(obj)
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
PlayerData(
|
||||
MakeAppearanceData(obj),
|
||||
MakeCharacterData(obj),
|
||||
|
|
@ -33,10 +32,10 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
|
|||
)
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
|
||||
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
|
||||
import AvatarConverter._
|
||||
Success(
|
||||
if(obj.VehicleSeated.isEmpty) {
|
||||
if (obj.VehicleSeated.isEmpty) {
|
||||
DetailedPlayerData.apply(
|
||||
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
|
||||
MakeAppearanceData(obj),
|
||||
|
|
@ -44,8 +43,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
|
|||
MakeDetailedInventoryData(obj),
|
||||
GetDrawnSlot(obj)
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
DetailedPlayerData.apply(
|
||||
MakeAppearanceData(obj),
|
||||
MakeDetailedCharacterData(obj),
|
||||
|
|
@ -58,14 +56,15 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
|
|||
}
|
||||
|
||||
object AvatarConverter {
|
||||
|
||||
/**
|
||||
* Compose some data from a `Player` into a representation common to both `CharacterData` and `DetailedCharacterData`.
|
||||
* @param obj the `Player` game object
|
||||
* @return the resulting `CharacterAppearanceData`
|
||||
*/
|
||||
def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
|
||||
val alt_model_flag : Boolean = obj.isBackpack
|
||||
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
|
||||
def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
|
||||
val alt_model_flag: Boolean = obj.isBackpack
|
||||
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
|
||||
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, obj.Voice),
|
||||
CommonFieldData(
|
||||
obj.Faction,
|
||||
|
|
@ -86,7 +85,7 @@ object AvatarConverter {
|
|||
0,
|
||||
0
|
||||
)
|
||||
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
|
||||
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
|
||||
0L,
|
||||
outfit_name = "",
|
||||
outfit_logo = 0,
|
||||
|
|
@ -109,14 +108,13 @@ object AvatarConverter {
|
|||
CharacterAppearanceData(aa, ab, RibbonBars())
|
||||
}
|
||||
|
||||
def MakeCharacterData(obj : Player) : (Boolean,Boolean)=>CharacterData = {
|
||||
def MakeCharacterData(obj: Player): (Boolean, Boolean) => CharacterData = {
|
||||
val MaxArmor = obj.MaxArmor
|
||||
CharacterData(
|
||||
StatConverter.Health(obj.Health, obj.MaxHealth),
|
||||
if(MaxArmor == 0) {
|
||||
if (MaxArmor == 0) {
|
||||
0
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
StatConverter.Health(obj.Armor, MaxArmor)
|
||||
},
|
||||
DressBattleRank(obj),
|
||||
|
|
@ -127,43 +125,59 @@ object AvatarConverter {
|
|||
)
|
||||
}
|
||||
|
||||
def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
|
||||
val bep : Long = obj.BEP
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
|
||||
val bep: Long = obj.BEP
|
||||
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
|
||||
else { None }
|
||||
val ba: DetailedCharacterA = DetailedCharacterA(
|
||||
bep,
|
||||
obj.CEP,
|
||||
0L, 0L, 0L,
|
||||
obj.MaxHealth, obj.Health,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
obj.MaxHealth,
|
||||
obj.Health,
|
||||
false,
|
||||
obj.Armor,
|
||||
0L,
|
||||
obj.MaxStamina, obj.Stamina,
|
||||
obj.MaxStamina,
|
||||
obj.Stamina,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
0,
|
||||
0,
|
||||
0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
obj.Certifications.toList.sortBy(_.id) //TODO is sorting necessary?
|
||||
)
|
||||
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
|
||||
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
|
||||
None,
|
||||
MakeImplantEntries(obj),
|
||||
Nil, Nil,
|
||||
Nil,
|
||||
Nil,
|
||||
obj.FirstTimeEvents,
|
||||
tutorials = List.empty[String], //TODO tutorial list
|
||||
0L, 0L, 0L, 0L, 0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
Some(DCDExtra2(0, 0)),
|
||||
Nil, Nil, false,
|
||||
Nil,
|
||||
Nil,
|
||||
false,
|
||||
MakeCosmetics(obj)
|
||||
)
|
||||
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
|
||||
pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
|
||||
}
|
||||
|
||||
def MakeInventoryData(obj : Player) : InventoryData = {
|
||||
def MakeInventoryData(obj: Player): InventoryData = {
|
||||
InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot))
|
||||
}
|
||||
|
||||
def MakeDetailedInventoryData(obj : Player) : InventoryData = {
|
||||
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot))
|
||||
def MakeDetailedInventoryData(obj: Player): InventoryData = {
|
||||
InventoryData(
|
||||
(MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -172,18 +186,15 @@ object AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return the resulting uniform upgrade level
|
||||
*/
|
||||
private def DressBattleRank(obj : Player) : UniformStyle.Value = {
|
||||
val bep : Long = obj.BEP
|
||||
if(bep > 2583440) { //BR25+
|
||||
private def DressBattleRank(obj: Player): UniformStyle.Value = {
|
||||
val bep: Long = obj.BEP
|
||||
if (bep > 2583440) { //BR25+
|
||||
UniformStyle.ThirdUpgrade
|
||||
}
|
||||
else if(bep > 308989) { //BR14+
|
||||
} else if (bep > 308989) { //BR14+
|
||||
UniformStyle.SecondUpgrade
|
||||
}
|
||||
else if(bep > 44999) { //BR7+
|
||||
} else if (bep > 44999) { //BR7+
|
||||
UniformStyle.FirstUpgrade
|
||||
}
|
||||
else { //BR1+
|
||||
} else { //BR1+
|
||||
UniformStyle.Normal
|
||||
}
|
||||
}
|
||||
|
|
@ -194,24 +205,19 @@ object AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return the resulting uniform upgrade level
|
||||
*/
|
||||
private def DressCommandRank(obj : Player) : Int = {
|
||||
private def DressCommandRank(obj: Player): Int = {
|
||||
val cep = obj.CEP
|
||||
if(cep > 599999) {
|
||||
if (cep > 599999) {
|
||||
5
|
||||
}
|
||||
else if(cep > 299999) {
|
||||
} else if (cep > 299999) {
|
||||
4
|
||||
}
|
||||
else if(cep > 149999) {
|
||||
} else if (cep > 149999) {
|
||||
3
|
||||
}
|
||||
else if(cep > 49999) {
|
||||
} else if (cep > 49999) {
|
||||
2
|
||||
}
|
||||
else if(cep > 9999) {
|
||||
} else if (cep > 9999) {
|
||||
1
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
@ -222,17 +228,19 @@ object AvatarConverter {
|
|||
* @return the resulting implant `List`
|
||||
* @see `ImplantEntry` in `DetailedCharacterData`
|
||||
*/
|
||||
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
|
||||
private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
|
||||
//val numImplants : Int = DetailedCharacterData.numberOfImplantSlots(obj.BEP)
|
||||
//val implants = obj.Implants
|
||||
obj.Implants.map({ case(implant, initialization, _) =>
|
||||
if(initialization == 0) {
|
||||
ImplantEntry(implant, None)
|
||||
}
|
||||
else {
|
||||
ImplantEntry(implant, Some(math.max(0,initialization).toInt))
|
||||
}
|
||||
}).toList
|
||||
obj.Implants
|
||||
.map({
|
||||
case (implant, initialization, _) =>
|
||||
if (initialization == 0) {
|
||||
ImplantEntry(implant, None)
|
||||
} else {
|
||||
ImplantEntry(implant, Some(math.max(0, initialization).toInt))
|
||||
}
|
||||
})
|
||||
.toList
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,12 +248,12 @@ object AvatarConverter {
|
|||
* @param implants a `Sequence` of `ImplantSlot` objects
|
||||
* @return the effect of an active implant
|
||||
*/
|
||||
private def MakeImplantEffectList(implants : Seq[(ImplantType.Value, Long, Boolean)]) : List[ImplantEffects.Value] = {
|
||||
private def MakeImplantEffectList(implants: Seq[(ImplantType.Value, Long, Boolean)]): List[ImplantEffects.Value] = {
|
||||
implants.collect {
|
||||
case (ImplantType.AdvancedRegen,_,true) => ImplantEffects.RegenEffects
|
||||
case (ImplantType.DarklightVision,_,true) => ImplantEffects.DarklightEffects
|
||||
case (ImplantType.PersonalShield,_,true) => ImplantEffects.PersonalShieldEffects
|
||||
case (ImplantType.Surge,_,true) => ImplantEffects.SurgeEffects
|
||||
case (ImplantType.AdvancedRegen, _, true) => ImplantEffects.RegenEffects
|
||||
case (ImplantType.DarklightVision, _, true) => ImplantEffects.DarklightEffects
|
||||
case (ImplantType.PersonalShield, _, true) => ImplantEffects.PersonalShieldEffects
|
||||
case (ImplantType.Surge, _, true) => ImplantEffects.SurgeEffects
|
||||
}.toList
|
||||
}
|
||||
|
||||
|
|
@ -257,11 +265,10 @@ object AvatarConverter {
|
|||
* @see `Cosmetics`
|
||||
* @return the `Cosmetics` options
|
||||
*/
|
||||
def MakeCosmetics(obj : Player) : Option[Cosmetics] =
|
||||
if(DetailedCharacterData.isBR24(obj.BEP)) {
|
||||
def MakeCosmetics(obj: Player): Option[Cosmetics] =
|
||||
if (DetailedCharacterData.isBR24(obj.BEP)) {
|
||||
obj.PersonalStyleFeatures.orElse(Some(Cosmetics()))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
|
|
@ -272,11 +279,16 @@ object AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return a list of all items that were in the inventory in decoded packet form
|
||||
*/
|
||||
private def MakeInventory(obj : Player) : List[InternalSlot] = {
|
||||
private def MakeInventory(obj: Player): List[InternalSlot] = {
|
||||
obj.Inventory.Items
|
||||
.map(item => {
|
||||
val equip : Equipment = item.obj
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get)
|
||||
val equip: Equipment = item.obj
|
||||
InternalSlot(
|
||||
equip.Definition.ObjectId,
|
||||
equip.GUID,
|
||||
item.start,
|
||||
equip.Definition.Packet.DetailedConstructorData(equip).get
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +301,7 @@ object AvatarConverter {
|
|||
* @param builder the function used to transform to the decoded packet form
|
||||
* @return a list of all items that were in the holsters in decoded packet form
|
||||
*/
|
||||
private def MakeHolsters(obj : Player, builder : (Int, Equipment) => InternalSlot) : List[InternalSlot] = {
|
||||
private def MakeHolsters(obj: Player, builder: (Int, Equipment) => InternalSlot): List[InternalSlot] = {
|
||||
recursiveMakeHolsters(obj.Holsters().iterator, builder)
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +312,7 @@ object AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return a list of any item that was in the fifth holster in decoded packet form
|
||||
*/
|
||||
private def MakeFifthSlot(obj : Player) : List[InternalSlot] = {
|
||||
private def MakeFifthSlot(obj: Player): List[InternalSlot] = {
|
||||
obj.Slot(5).Equipment match {
|
||||
case Some(equip) =>
|
||||
BuildDetailedEquipment(5, equip) :: Nil
|
||||
|
|
@ -315,7 +327,7 @@ object AvatarConverter {
|
|||
* @param equip the game object
|
||||
* @return the game object in decoded packet form
|
||||
*/
|
||||
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = {
|
||||
private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.ConstructorData(equip).get)
|
||||
}
|
||||
|
||||
|
|
@ -325,8 +337,13 @@ object AvatarConverter {
|
|||
* @param equip the game object
|
||||
* @return the game object in decoded packet form
|
||||
*/
|
||||
def BuildDetailedEquipment(index : Int, equip : Equipment) : InternalSlot = {
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get)
|
||||
def BuildDetailedEquipment(index: Int, equip: Equipment): InternalSlot = {
|
||||
InternalSlot(
|
||||
equip.Definition.ObjectId,
|
||||
equip.GUID,
|
||||
index,
|
||||
equip.Definition.Packet.DetailedConstructorData(equip).get
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -337,22 +354,25 @@ object AvatarConverter {
|
|||
* @param index which holster is currently being explored
|
||||
* @return the `List` of inventory data created from the holsters
|
||||
*/
|
||||
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], builder : (Int, Equipment) => InternalSlot, list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursiveMakeHolsters(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
builder: (Int, Equipment) => InternalSlot,
|
||||
list: List[InternalSlot] = Nil,
|
||||
index: Int = 0
|
||||
): List[InternalSlot] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
val slot : EquipmentSlot = iter.next
|
||||
if(slot.Equipment.isDefined) {
|
||||
val equip : Equipment = slot.Equipment.get
|
||||
} else {
|
||||
val slot: EquipmentSlot = iter.next
|
||||
if (slot.Equipment.isDefined) {
|
||||
val equip: Equipment = slot.Equipment.get
|
||||
recursiveMakeHolsters(
|
||||
iter,
|
||||
builder,
|
||||
list :+ builder(index, equip),
|
||||
index + 1
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
recursiveMakeHolsters(iter, builder, list, index + 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -363,10 +383,10 @@ object AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return the holster's Enumeration value
|
||||
*/
|
||||
def GetDrawnSlot(obj : Player) : DrawnSlot.Value = {
|
||||
def GetDrawnSlot(obj: Player): DrawnSlot.Value = {
|
||||
obj.DrawnSlot match {
|
||||
case Player.HandsDownSlot | Player.FreeHandSlot => DrawnSlot.None
|
||||
case n => DrawnSlot(n)
|
||||
case n => DrawnSlot(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class BoomerTriggerConverter extends ObjectCreateConverter[SimpleItem]() {
|
||||
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = {
|
||||
override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
|
||||
Success(HandheldData(CommonFieldData()))
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedConstructionToolData] = {
|
||||
Success(DetailedConstructionToolData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
))
|
||||
override def DetailedConstructorData(obj: SimpleItem): Try[DetailedConstructionToolData] = {
|
||||
Success(
|
||||
DetailedConstructionToolData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
package net.psforever.objects.definition.converter
|
||||
|
||||
import net.psforever.objects.{Player, Tool}
|
||||
import net.psforever.objects.equipment.{Equipment, EquipmentSlot}
|
||||
import net.psforever.objects.equipment.EquipmentSlot
|
||||
import net.psforever.packet.game.objectcreate._
|
||||
import net.psforever.types.{PlanetSideGUID, _}
|
||||
|
||||
|
|
@ -15,9 +15,10 @@ import scala.util.{Failure, Success, Try}
|
|||
* Details that would not be apparent on that screen such as implants or certifications are ignored.
|
||||
*/
|
||||
class CharacterSelectConverter extends AvatarConverter {
|
||||
override def ConstructorData(obj : Player) : Try[PlayerData] = Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
|
||||
override def ConstructorData(obj: Player): Try[PlayerData] =
|
||||
Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
|
||||
|
||||
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
|
||||
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
|
||||
Success(
|
||||
DetailedPlayerData.apply(
|
||||
PlacementData(0, 0, 0),
|
||||
|
|
@ -35,8 +36,8 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
* @see `AvatarConverter.MakeAppearanceData`
|
||||
* @return the resulting `CharacterAppearanceData`
|
||||
*/
|
||||
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
|
||||
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
|
||||
private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
|
||||
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
|
||||
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, CharacterVoice.Mute),
|
||||
CommonFieldData(
|
||||
obj.Faction,
|
||||
|
|
@ -57,7 +58,7 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
0,
|
||||
0
|
||||
)
|
||||
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
|
||||
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
|
||||
0L,
|
||||
outfit_name = "",
|
||||
outfit_logo = 0,
|
||||
|
|
@ -80,35 +81,49 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
CharacterAppearanceData(aa, ab, RibbonBars())
|
||||
}
|
||||
|
||||
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
|
||||
val bep : Long = obj.BEP
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
|
||||
val bep: Long = obj.BEP
|
||||
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
|
||||
else { None }
|
||||
val ba: DetailedCharacterA = DetailedCharacterA(
|
||||
bep,
|
||||
obj.CEP,
|
||||
0L, 0L, 0L,
|
||||
1, 1,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
1,
|
||||
1,
|
||||
false,
|
||||
0,
|
||||
0L,
|
||||
1, 1,
|
||||
1,
|
||||
1,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
0,
|
||||
0,
|
||||
0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
certs = List.empty[CertificationType.Value]
|
||||
)
|
||||
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
|
||||
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
|
||||
None,
|
||||
MakeImplantEntries(obj), //necessary for correct stream length
|
||||
Nil, Nil,
|
||||
Nil,
|
||||
Nil,
|
||||
firstTimeEvents = List.empty[String],
|
||||
tutorials = List.empty[String],
|
||||
0L, 0L, 0L, 0L, 0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
Some(DCDExtra2(0, 0)),
|
||||
Nil, Nil, false,
|
||||
Nil,
|
||||
Nil,
|
||||
false,
|
||||
AvatarConverter.MakeCosmetics(obj)
|
||||
)
|
||||
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
|
||||
pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,7 +132,7 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
* @return the resulting implant `List`
|
||||
* @see `ImplantEntry` in `DetailedCharacterData`
|
||||
*/
|
||||
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
|
||||
private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
|
||||
List.fill[ImplantEntry](DetailedCharacterData.numberOfImplantSlots(obj.BEP))(ImplantEntry(ImplantType.None, None))
|
||||
}
|
||||
|
||||
|
|
@ -129,14 +144,17 @@ class CharacterSelectConverter extends AvatarConverter {
|
|||
* @see `AvatarConverter.recursiveMakeHolsters`
|
||||
* @return the `List` of inventory data created from the holsters
|
||||
*/
|
||||
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursiveMakeHolsters(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
list: List[InternalSlot] = Nil,
|
||||
index: Int = 0
|
||||
): List[InternalSlot] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
val slot : EquipmentSlot = iter.next
|
||||
} else {
|
||||
val slot: EquipmentSlot = iter.next
|
||||
slot.Equipment match {
|
||||
case Some(equip : Tool) =>
|
||||
case Some(equip: Tool) =>
|
||||
val jammed = equip.Jammed
|
||||
equip.Jammed = false
|
||||
val slot = AvatarConverter.BuildDetailedEquipment(index, equip)
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ package net.psforever.objects.definition.converter
|
|||
|
||||
import net.psforever.objects.SimpleItem
|
||||
import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedCommandDetonaterData, HandheldData}
|
||||
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
||||
import net.psforever.types.PlanetSideGUID
|
||||
|
||||
import scala.util.{Success, Try}
|
||||
|
||||
class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
|
||||
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = {
|
||||
override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
|
||||
Success(
|
||||
HandheldData(
|
||||
CommonFieldData(
|
||||
|
|
@ -26,7 +26,7 @@ class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
|
|||
)
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedCommandDetonaterData] = {
|
||||
override def DetailedConstructorData(obj: SimpleItem): Try[DetailedCommandDetonaterData] = {
|
||||
Success(
|
||||
DetailedCommandDetonaterData(
|
||||
CommonFieldData(
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@ import scala.annotation.tailrec
|
|||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class CorpseConverter extends AvatarConverter {
|
||||
override def ConstructorData(obj : Player) : Try[PlayerData] =
|
||||
override def ConstructorData(obj: Player): Try[PlayerData] =
|
||||
Failure(new Exception("CorpseConverter should not be used to generate CharacterData"))
|
||||
|
||||
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
|
||||
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
|
||||
Success(
|
||||
DetailedPlayerData.apply(
|
||||
PlacementData(obj.Position, Vector3(0,0, obj.Orientation.z)),
|
||||
PlacementData(obj.Position, Vector3(0, 0, obj.Orientation.z)),
|
||||
MakeAppearanceData(obj),
|
||||
MakeDetailedCharacterData(obj),
|
||||
InventoryData((MakeHolsters(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)),
|
||||
|
|
@ -30,8 +30,8 @@ class CorpseConverter extends AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return the resulting `CharacterAppearanceData`
|
||||
*/
|
||||
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
|
||||
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
|
||||
private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
|
||||
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
|
||||
BasicCharacterData(obj.Name, obj.Faction, CharacterGender.Male, 0, CharacterVoice.Mute),
|
||||
CommonFieldData(
|
||||
obj.Faction,
|
||||
|
|
@ -52,7 +52,7 @@ class CorpseConverter extends AvatarConverter {
|
|||
0,
|
||||
0
|
||||
)
|
||||
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
|
||||
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
|
||||
0L,
|
||||
outfit_name = "",
|
||||
outfit_logo = 0,
|
||||
|
|
@ -75,34 +75,48 @@ class CorpseConverter extends AvatarConverter {
|
|||
CharacterAppearanceData(aa, ab, RibbonBars())
|
||||
}
|
||||
|
||||
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
|
||||
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
|
||||
val ba : DetailedCharacterA = DetailedCharacterA(
|
||||
private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
|
||||
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
|
||||
else { None }
|
||||
val ba: DetailedCharacterA = DetailedCharacterA(
|
||||
bep = 0L,
|
||||
cep = 0L,
|
||||
0L, 0L, 0L,
|
||||
0, 0,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0L,
|
||||
0, 0,
|
||||
0,
|
||||
0,
|
||||
maxOpt,
|
||||
0, 0, 0L,
|
||||
0,
|
||||
0,
|
||||
0L,
|
||||
List(0, 0, 0, 0, 0, 0),
|
||||
certs = List.empty[CertificationType.Value]
|
||||
)
|
||||
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
|
||||
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
|
||||
None,
|
||||
implants = List.empty[ImplantEntry],
|
||||
Nil, Nil,
|
||||
Nil,
|
||||
Nil,
|
||||
firstTimeEvents = List.empty[String],
|
||||
tutorials = List.empty[String],
|
||||
0L, 0L, 0L, 0L, 0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
Some(DCDExtra2(0, 0)),
|
||||
Nil, Nil, false,
|
||||
Nil,
|
||||
Nil,
|
||||
false,
|
||||
cosmetics = None
|
||||
)
|
||||
(pad_length : Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length)
|
||||
(pad_length: Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,11 +126,11 @@ class CorpseConverter extends AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return a list of all items that were in the inventory in decoded packet form
|
||||
*/
|
||||
private def MakeInventory(obj : Player) : List[InternalSlot] = {
|
||||
private def MakeInventory(obj: Player): List[InternalSlot] = {
|
||||
obj.Inventory.Items
|
||||
.map(item => {
|
||||
val equip : Equipment = item.obj
|
||||
BuildEquipment(item.start, equip)
|
||||
val equip: Equipment = item.obj
|
||||
BuildEquipment(item.start, equip)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +142,7 @@ class CorpseConverter extends AvatarConverter {
|
|||
* @param obj the `Player` game object
|
||||
* @return a list of all items that were in the holsters in decoded packet form
|
||||
*/
|
||||
private def MakeHolsters(obj : Player) : List[InternalSlot] = {
|
||||
private def MakeHolsters(obj: Player): List[InternalSlot] = {
|
||||
recursiveMakeHolsters(obj.Holsters().iterator)
|
||||
}
|
||||
|
||||
|
|
@ -139,21 +153,23 @@ class CorpseConverter extends AvatarConverter {
|
|||
* @param index which holster is currently being explored
|
||||
* @return the `List` of inventory data created from the holsters
|
||||
*/
|
||||
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
|
||||
if(!iter.hasNext) {
|
||||
@tailrec private def recursiveMakeHolsters(
|
||||
iter: Iterator[EquipmentSlot],
|
||||
list: List[InternalSlot] = Nil,
|
||||
index: Int = 0
|
||||
): List[InternalSlot] = {
|
||||
if (!iter.hasNext) {
|
||||
list
|
||||
}
|
||||
else {
|
||||
val slot : EquipmentSlot = iter.next
|
||||
if(slot.Equipment.isDefined) {
|
||||
val equip : Equipment = slot.Equipment.get
|
||||
} else {
|
||||
val slot: EquipmentSlot = iter.next
|
||||
if (slot.Equipment.isDefined) {
|
||||
val equip: Equipment = slot.Equipment.get
|
||||
recursiveMakeHolsters(
|
||||
iter,
|
||||
list :+ BuildEquipment(index, equip),
|
||||
index + 1
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
recursiveMakeHolsters(iter, list, index + 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -165,8 +181,13 @@ class CorpseConverter extends AvatarConverter {
|
|||
* @param equip the game object
|
||||
* @return the game object in decoded packet form
|
||||
*/
|
||||
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = {
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get)
|
||||
private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
|
||||
InternalSlot(
|
||||
equip.Definition.ObjectId,
|
||||
equip.GUID,
|
||||
index,
|
||||
equip.Definition.Packet.DetailedConstructorData(equip).get
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,17 @@ import net.psforever.packet.game.objectcreate.{DestroyedVehicleData, PlacementDa
|
|||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class DestroyedVehicleConverter extends ObjectCreateConverter[Vehicle]() {
|
||||
override def DetailedConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] =
|
||||
Failure(new Exception("DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)"))
|
||||
override def DetailedConstructorData(obj: Vehicle): Try[DestroyedVehicleData] =
|
||||
Failure(
|
||||
new Exception(
|
||||
"DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)"
|
||||
)
|
||||
)
|
||||
|
||||
override def ConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] = {
|
||||
if(obj.Health > 0) {
|
||||
override def ConstructorData(obj: Vehicle): Try[DestroyedVehicleData] = {
|
||||
if (obj.Health > 0) {
|
||||
Failure(new Exception("Vehicle used on DestroyedVehicleConverter has not yet been destroyed (Health == 0)"))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Success(DestroyedVehicleData(PlacementData(obj.Position, obj.Orientation)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import net.psforever.types.PlanetSideGUID
|
|||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
|
||||
override def DetailedConstructorData(obj : Vehicle) : Try[DroppodData] =
|
||||
override def DetailedConstructorData(obj: Vehicle): Try[DroppodData] =
|
||||
Failure(new Exception("DroppodConverter should not be used to generate detailed DroppodData (nothing should)"))
|
||||
|
||||
override def ConstructorData(obj : Vehicle) : Try[DroppodData] = {
|
||||
override def ConstructorData(obj: Vehicle): Try[DroppodData] = {
|
||||
val health = StatConverter.Health(obj.Health, obj.MaxHealth)
|
||||
if(health > 0) { //active
|
||||
if (health > 0) { //active
|
||||
Success(
|
||||
DroppodData(
|
||||
CommonFieldDataWithPlacement(
|
||||
|
|
@ -29,7 +29,7 @@ class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
|
|||
v5 = None,
|
||||
obj.Owner match {
|
||||
case Some(owner) => owner
|
||||
case None => PlanetSideGUID(0)
|
||||
case None => PlanetSideGUID(0)
|
||||
}
|
||||
)
|
||||
),
|
||||
|
|
@ -38,8 +38,7 @@ class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
|
|||
unk = false
|
||||
)
|
||||
)
|
||||
}
|
||||
else { //destroyed
|
||||
} else { //destroyed
|
||||
Success(
|
||||
DroppodData(
|
||||
CommonFieldDataWithPlacement(
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ import net.psforever.types.PlanetSideGUID
|
|||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
|
||||
override def ConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] = {
|
||||
override def ConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] = {
|
||||
val health = StatConverter.Health(obj.Health, obj.MaxHealth)
|
||||
if(health > 3) {
|
||||
if (health > 3) {
|
||||
Success(
|
||||
OneMannedFieldTurretData(
|
||||
CommonFieldDataWithPlacement(
|
||||
|
|
@ -28,7 +28,7 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
|
|||
None,
|
||||
obj.Owner match {
|
||||
case Some(owner) => owner
|
||||
case None => PlanetSideGUID(0)
|
||||
case None => PlanetSideGUID(0)
|
||||
}
|
||||
)
|
||||
),
|
||||
|
|
@ -36,8 +36,7 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
|
|||
Some(InventoryData(FieldTurretConverter.MakeMountings(obj)))
|
||||
)
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Success(
|
||||
OneMannedFieldTurretData(
|
||||
CommonFieldDataWithPlacement(
|
||||
|
|
@ -60,17 +59,19 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
|
|||
}
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] =
|
||||
override def DetailedConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] =
|
||||
Failure(new Exception("converter should not be used to generate detailed OneMannedFieldTurretData"))
|
||||
}
|
||||
|
||||
object FieldTurretConverter {
|
||||
private def MakeMountings(obj : WeaponTurret) : List[InventoryItemData.InventoryItem] = {
|
||||
obj.Weapons.map({
|
||||
case(index, slot) =>
|
||||
val equip : Equipment = slot.Equipment.get
|
||||
val equipDef = equip.Definition
|
||||
InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get)
|
||||
}).toList
|
||||
private def MakeMountings(obj: WeaponTurret): List[InventoryItemData.InventoryItem] = {
|
||||
obj.Weapons
|
||||
.map({
|
||||
case (index, slot) =>
|
||||
val equip: Equipment = slot.Equipment.get
|
||||
val equipDef = equip.Definition
|
||||
InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get)
|
||||
})
|
||||
.toList
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
|||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSideGameObject with TelepadLike]() {
|
||||
override def ConstructorData(obj : PlanetSideGameObject with TelepadLike) : Try[TelepadDeployableData] = {
|
||||
override def ConstructorData(obj: PlanetSideGameObject with TelepadLike): Try[TelepadDeployableData] = {
|
||||
obj.Router match {
|
||||
case Some(PlanetSideGUID(0)) =>
|
||||
Failure(new IllegalStateException("InternalTelepadDeployableConverter: knowledge of parent Router is null"))
|
||||
|
|
@ -34,7 +34,9 @@ class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSid
|
|||
)
|
||||
|
||||
case None =>
|
||||
Failure(new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router"))
|
||||
Failure(
|
||||
new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedAmmoBoxD
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class KitConverter extends ObjectCreateConverter[Kit]() {
|
||||
override def ConstructorData(obj : Kit) : Try[CommonFieldData] = {
|
||||
override def ConstructorData(obj: Kit): Try[CommonFieldData] = {
|
||||
Success(CommonFieldData()(false))
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : Kit) : Try[DetailedAmmoBoxData] = {
|
||||
override def DetailedConstructorData(obj: Kit): Try[DetailedAmmoBoxData] = {
|
||||
Success(DetailedAmmoBoxData(0, 1))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
|
|||
import scala.util.{Success, Try}
|
||||
|
||||
class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]() {
|
||||
override def ConstructorData(obj : LockerEquipment) : Try[LockerContainerData] = {
|
||||
override def ConstructorData(obj: LockerEquipment): Try[LockerContainerData] = {
|
||||
MakeInventory(obj.Inventory) match {
|
||||
case Nil =>
|
||||
Success(LockerContainerData(None))
|
||||
|
|
@ -19,18 +19,21 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
|
|||
}
|
||||
}
|
||||
|
||||
override def DetailedConstructorData(obj : LockerEquipment) : Try[DetailedLockerContainerData] = {
|
||||
if(obj.Inventory.Size > 0) {
|
||||
Success(DetailedLockerContainerData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
Some(InventoryData(MakeDetailedInventory(obj.Inventory)))
|
||||
))
|
||||
}
|
||||
else {
|
||||
Success(DetailedLockerContainerData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
None
|
||||
))
|
||||
override def DetailedConstructorData(obj: LockerEquipment): Try[DetailedLockerContainerData] = {
|
||||
if (obj.Inventory.Size > 0) {
|
||||
Success(
|
||||
DetailedLockerContainerData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
Some(InventoryData(MakeDetailedInventory(obj.Inventory)))
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Success(
|
||||
DetailedLockerContainerData(
|
||||
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
|
||||
None
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -40,13 +43,18 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
|
|||
* @param inv the inventory container
|
||||
* @return a list of all items that were in the inventory in decoded packet form
|
||||
*/
|
||||
private def MakeInventory(inv : GridInventory) : List[InternalSlot] = {
|
||||
private def MakeInventory(inv: GridInventory): List[InternalSlot] = {
|
||||
inv.Items
|
||||
.map(item => {
|
||||
val equip : Equipment = item.obj
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.ConstructorData(equip).get)
|
||||
val equip: Equipment = item.obj
|
||||
InternalSlot(
|
||||
equip.Definition.ObjectId,
|
||||
equip.GUID,
|
||||
item.start,
|
||||
equip.Definition.Packet.ConstructorData(equip).get
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a list of contained items into a list of contained `InternalSlot` objects.
|
||||
|
|
@ -54,11 +62,16 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
|
|||
* @param inv the inventory container
|
||||
* @return a list of all items that were in the inventory in decoded packet form
|
||||
*/
|
||||
private def MakeDetailedInventory(inv : GridInventory) : List[InternalSlot] = {
|
||||
private def MakeDetailedInventory(inv: GridInventory): List[InternalSlot] = {
|
||||
inv.Items
|
||||
.map(item => {
|
||||
val equip : Equipment = item.obj
|
||||
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get)
|
||||
val equip: Equipment = item.obj
|
||||
InternalSlot(
|
||||
equip.Definition.ObjectId,
|
||||
equip.GUID,
|
||||
item.start,
|
||||
equip.Definition.Packet.DetailedConstructorData(equip).get
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue