merge changes from the defunct ubot
This commit is contained in:
parent
1904b22977
commit
cf501b75b7
90 changed files with 11977 additions and 3907 deletions
18
.gitattributes
vendored
18
.gitattributes
vendored
|
|
@ -2,20 +2,6 @@
|
|||
* text=auto
|
||||
|
||||
# Custom for Visual Studio
|
||||
*.sln merge=union
|
||||
*.csproj merge=union
|
||||
*.vbproj merge=union
|
||||
*.fsproj merge=union
|
||||
*.dbproj merge=union
|
||||
*.sln merge=union
|
||||
*.vcxproj merge=union
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
|
|
|
|||
75
.gitignore
vendored
75
.gitignore
vendored
|
|
@ -1,71 +1,8 @@
|
|||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must ends with two \r.
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
/project/.vs
|
||||
/project/enc_temp_folder
|
||||
/.vs
|
||||
|
||||
*.pdb
|
||||
*.asm
|
||||
*.tlog
|
||||
*.obj
|
||||
*.log
|
||||
*.manifest
|
||||
*.map
|
||||
*.res
|
||||
*.lib
|
||||
*.exp
|
||||
*.ilk
|
||||
*.opensdf
|
||||
*.dll
|
||||
*.sdf
|
||||
*.suo
|
||||
*.idb
|
||||
*.vspx
|
||||
*.so
|
||||
*.user
|
||||
*.psess
|
||||
*.opendb
|
||||
*.aps
|
||||
*.db
|
||||
*.enc
|
||||
*.xml
|
||||
*.vsp
|
||||
*.lastcodeanalysissucceeded
|
||||
*.json
|
||||
*.html
|
||||
*.settings
|
||||
*.sarif
|
||||
*.txt
|
||||
|
||||
vc/release
|
||||
vc/debug
|
||||
vc/.vs
|
||||
vc/enc_temp_folder
|
||||
32
.travis.yml
32
.travis.yml
|
|
@ -1,32 +0,0 @@
|
|||
language: cpp
|
||||
dist: bionic
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc6-dev-i386
|
||||
- linux-libc-dev
|
||||
- gcc-multilib
|
||||
- g++-multilib
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
before_script:
|
||||
- sed -i.bak "s/unspecified_hash/$(git rev-parse HEAD 2>/dev/null)/g;s/unspecified_author/$(git log --pretty="%ae" -1 2>/dev/null)/g;s/0000/$(git rev-list HEAD --count 2>/dev/null)/g" include/resource.h && rm include/resource.h.bak
|
||||
|
||||
script:
|
||||
- cd project && CC=clang && make all
|
||||
|
||||
after_success:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||
- curl -F "key=$CI_KEY" -F "mode=build" -F "type=release" -F "lib=@./release/yapb.so" https://yapb.ru/agent/ci.php
|
||||
- curl -F "key=$CI_KEY" -F "mode=build" -F "type=debug" -F "lib=@./debug/yapb.so" https://yapb.ru/agent/ci.php
|
||||
- fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
- curl -F "key=$CI_KEY" -F "mode=build" -F "type=release" -F "lib=@./release/yapb.dylib" https://yapb.ru/agent/ci.php
|
||||
- curl -F "key=$CI_KEY" -F "mode=build" -F "type=debug" -F "lib=@./debug/yapb.dylib" https://yapb.ru/agent/ci.php
|
||||
- fi
|
||||
|
|
@ -1 +0,0 @@
|
|||
include $(call all-subdir-makefiles)
|
||||
687
LICENSE.txt
687
LICENSE.txt
|
|
@ -1,21 +1,674 @@
|
|||
The MIT License (MIT)
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (c) 2004-2019 Yet Another POD-Bot Contributors <yapb@entix.io>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Preamble
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
14
README.md
14
README.md
|
|
@ -1,12 +1,6 @@
|
|||
Yet Another Ping Of Death Bot
|
||||
=============
|
||||
## YaPB
|
||||
The third party AI for Counter-Strike game.
|
||||
|
||||
AI opponent for Counter-Strike based on POD-Bot 2.6 which allows your to play good old Counter-Strike without connecting to any server, or fill your server with computer controlled players.
|
||||
AI opponent for Counter-Strike which allows your to play good old Counter-Strike without connecting to any server, or fill your server with computer controlled players.
|
||||
|
||||
Note that current status is maintenance and stabilization only. No new features are currently planned for bot.
|
||||
|
||||
Build Status & Downloads:
|
||||
|
||||
| Windows | Linux | Mac OS X | Coverity |
|
||||
| :------------: |:---------------:|:---------------:| :-----:|
|
||||
| [](https://ci.appveyor.com/project/jeefo/yapb) | [](https://travis-ci.org/jeefo/yapb) | [](https://travis-ci.org/jeefo/yapb) | [](https://scan.coverity.com/projects/5618)
|
||||
Note that current status is maintenance and stabilization only.
|
||||
|
|
|
|||
73
cfg/addons/yapb/conf/avatars.cfg
Normal file
73
cfg/addons/yapb/conf/avatars.cfg
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: avatars.cfg
|
||||
;
|
||||
; This is a list of 64-bit Steam IDs that are used to display avatar for
|
||||
; bots in scoreboard. There is currently limitation in counter-strike
|
||||
; that it will display only avatars of players friends. So this basically
|
||||
; currently useless until fix is found.
|
||||
;
|
||||
; Note: This is randomly taken Steam IDs. If you find yourself here, please
|
||||
; create an issue to remove your person from here.
|
||||
;
|
||||
|
||||
76561198824784299
|
||||
76561198007764214
|
||||
76561198282309907
|
||||
76561198173426854
|
||||
76561198189287387
|
||||
76561198454548206
|
||||
76561198813109996
|
||||
76561198357926853
|
||||
76561198964532315
|
||||
76561198078745340
|
||||
76561198029448247
|
||||
76561198971020119
|
||||
76561198281235027
|
||||
76561198160435588
|
||||
76561198451491670
|
||||
76561198314767015
|
||||
76561198848243467
|
||||
76561198798756599
|
||||
76561198127882879
|
||||
76561198049242617
|
||||
76561198247156514
|
||||
76561198120614644
|
||||
76561198205696041
|
||||
76561198149965375
|
||||
76561198109600465
|
||||
76561198094851203
|
||||
76561198824784299
|
||||
76561198142543831
|
||||
76561197997365684
|
||||
76561198975813864
|
||||
76561198799029556
|
||||
76561198007764214
|
||||
76561198282309907
|
||||
76561198173426854
|
||||
76561198189287387
|
||||
76561198454548206
|
||||
76561198813109996
|
||||
76561198357926853
|
||||
76561198964532315
|
||||
76561198187991066
|
||||
76561198131984268
|
||||
76561198418691427
|
||||
76561198165897856
|
||||
76561198393573327
|
||||
76561197987376673
|
||||
76561198198316937
|
||||
76561198416777179
|
||||
76561197969349762
|
||||
76561198344695316
|
||||
76561198273780774
|
||||
76561198179528373
|
||||
76561198315042113
|
||||
76561198815408627
|
||||
76561198835894201
|
||||
76561198350551375
|
||||
76561198433144450
|
||||
76561198100425157
|
||||
76561198977884245
|
||||
84
cfg/addons/yapb/conf/chatter.cfg
Normal file
84
cfg/addons/yapb/conf/chatter.cfg
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: chatter.cfg
|
||||
;
|
||||
; Configuration file contains chatter definitions for bots.
|
||||
;
|
||||
|
||||
RewritePath sound/radio/bot
|
||||
|
||||
Event Radio_CoverMe = ("cover_me", "cover_me2");
|
||||
// Event Radio_YouTakePoint = ("");
|
||||
// Event Radio_HoldPosition = ("");
|
||||
// Event Radio_RegroupTeam = ("");
|
||||
Event Radio_FollowMe = ("lead_on_sir", "lead_the_way_sir", "lead_the_way", "ok_sir_lets_go", "lead_on_commander", "lead_the_way_commander", "ok_cmdr_lets_go");
|
||||
Event Radio_TakingFire = ("taking_fire_need_assistance2", "i_could_use_some_help", "i_could_use_some_help_over_here", "help", "need_help", "need_help2", "im_in_trouble");
|
||||
|
||||
// Event Radio_GoGoGo = ("");
|
||||
// Event Radio_Fallback = ("");
|
||||
// Event Radio_StickTogether = ("");
|
||||
// Event Radio_GetInPosition = ("");
|
||||
// Event Radio_StormTheFront = ("");
|
||||
Event Radio_ReportTeam = ("report_in_team", "anyone_see_them", "anyone_see_anything", "where_are_they", "where_could_they_be");
|
||||
|
||||
Event Radio_Affirmative = ("affirmative", "no2", "roger_that", "me_too", "ill_come_with_you", "ill_go_with_you", "ill_go_too", "i_got_your_back", "i_got_your_back2", "im_with_you", "im_with_you", "sounds_like_a_plan", "good_idea");
|
||||
Event Radio_EnemySpotted = ("one_guy", "two_of_them", "theyre_all_over_the_place2", "the_actions_hot_here", "its_a_party");
|
||||
Event Radio_NeedBackup = ("taking_fire_need_assistance2", "i_could_use_some_help", "i_could_use_some_help_over_here", "help", "need_help", "need_help2", "im_in_trouble");
|
||||
Event Radio_SectorClear = ("clear", "clear2", "clear3", "clear4", "area_clear", "all_clear_here", "nothing_happening_over_here", "nothing_here", "theres_nobody_home");
|
||||
Event Radio_InPosition = ("lets_wait_here", "lets_hold_up_here_for_a_minute", "im_gonna_hang_back", "im_going_to_wait_here", "im_waiting_here");
|
||||
Event Radio_ReportingIn = ("reporting_in");
|
||||
// Event Radio_ShesGonnaBlow = ("");
|
||||
Event Radio_Negative = ("ahh_negative", "negative", "no2", "negative2", "i_dont_think_so", "naa", "no_thanks", "no", "nnno_sir", "no_sir");
|
||||
Event Radio_EnemyDown = ("enemy_down", "enemy_down2");
|
||||
|
||||
// end of radio, begin some voices (NOT SORTED)
|
||||
Event Chatter_SpotTheBomber = ("i_see_the_bomber", "theres_the_bomber", "hes_got_the_bomb", "hes_got_the_bomb2", "hes_got_the_package", "spotted_the_delivery_boy");
|
||||
Event Chatter_FriendlyFire = ("cut_it_out", "what_are_you_doing", "stop_it", "ow_its_me", "ow", "ouch", "im_on_your_side", "hold_your_fire", "hey", "hey2", "ouch", "ouch", "ouch");
|
||||
Event Chatter_DiePain = ("pain2", "pain4", "pain5", "pain8", "pain9", "pain10");
|
||||
Event Chatter_GotBlinded = ("ive_been_blinded", "my_eyes", "i_cant_see", "im_blind");
|
||||
Event Chatter_GoingToPlantBomb = ("im_gonna_go_plant", "im_gonna_go_plant_the_bomb");
|
||||
Event Chatter_RescuingHostages = ("the_hostages_are_with_me", "taking_the_hostages_to_safety", "ive_got_the_hostages", "i_have_the_hostages");
|
||||
Event Chatter_GoingToCamp = ("im_going_to_camp");
|
||||
Event Chatter_HearSomething = ("hang_on_i_heard_something", "i_hear_something", "i_heard_them", "i_heard_something_over_there");
|
||||
Event Chatter_TeamKill = ("what_happened", "noo", "oh_my_god", "oh_man", "oh_no_sad", "what_have_you_done");
|
||||
Event Chatter_ReportingIn = ("reporting_in");
|
||||
Event Chatter_GuardDroppedC4 = ("bombsite", "bombsite2", "i_got_a_covered", "im_camping_c");
|
||||
Event Chatter_Camp = ("im_camping");
|
||||
Event Chatter_PlantingC4 = ("planting_the_bomb", "planting");
|
||||
Event Chatter_DefusingC4 = ("defusing", "defusing_bomb", "defusing_bomb");
|
||||
Event Chatter_InCombat = ("attacking", "attacking_enemies", "engaging_enemies", "in_combat", "in_combat2", "returning_fire");
|
||||
Event Chatter_SeeksEnemy = ("lets_wait_here", "lets_hold_up_here_for_a_minute", "im_gonna_hang_back", "im_going_to_wait_here", "im_waiting_here");
|
||||
Event Chatter_Nothing = ("nothing_here", "nothing");
|
||||
Event Chatter_EnemyDown = ("hes_dead", "hes_down", "got_him", "dropped_him", "killed_him", "ruined_his_day", "wasted_him", "made_him_cry", "took_him_down", "took_him_out2", "took_him_out", "hes_broken", "hes_done");
|
||||
Event Chatter_UseHostage = ("talking_to_hostages", "rescuing_hostages");
|
||||
Event Chatter_FoundC4 = ("bombs_on_the_ground", "bombs_on_the_ground_here", "the_bomb_is_down", "the_bomb_is_on_the_ground", "they_dropped_the_bomb");
|
||||
Event Chatter_WonTheRound = ("good_job_team", "nice_work_team", "way_to_be_team", "well_done");
|
||||
Event Chatter_QuicklyWonTheRound = ("i_am_dangerous", "do_not_mess_with_me", "we_owned_them", "they_never_knew_what_hit_them", "thats_the_way_this_is_done", "and_thats_how_its_done", "owned", "yesss", "yesss2", "yea_baby", "whoo", "whoo2", "oh_yea");
|
||||
Event Chatter_ScaredEmotion = ("whoa", "uh_oh", "oh_no", "yikes", "oh", "oh_boy", "oh_boy2", "aah");
|
||||
Event Chatter_HeardEnemy = ("i_hear_them", "hang_on_i_heard_something", "i_hear_something", "i_heard_them", "i_heard_something_over_there");
|
||||
Event Chatter_SniperWarning = ("sniper", "sniper2", "watch_it_theres_a_sniper");
|
||||
Event Chatter_SniperKilled = ("got_the_sniper", "got_the_sniper2", "sniper_down", "took_out_the_sniper", "the_sniper_is_dead");
|
||||
Event Chatter_VIPSpotted = ("i_see_our_target", "target_spotted", "target_acquired");
|
||||
Event Chatter_GuardingVipSafety = ("watching_the_escape_route", "im_at_the_escape_zone", "watching_the_escape_zone", "guarding_the_escape_zone", "guarding_the_escape_zone2");
|
||||
Event Chatter_GoingToGuardVIPSafety = ("im_going_to_cover_the_escape_zone", "im_going_to_watch_the_escape_zone", "im_going_to_keep_an_eye_on_the_escape", "heading_to_the_escape_zone");
|
||||
Event Chatter_OneEnemyLeft = ("one_guy_left", "theres_one_left");
|
||||
Event Chatter_TwoEnemiesLeft = ("two_enemies_left", "two_to_go");
|
||||
Event Chatter_ThreeEnemiesLeft = ("three_left", "three_to_go", "three_to_go2");
|
||||
Event Chatter_NoEnemiesLeft = ("that_was_the_last_one", "that_was_it", "that_was_the_last_guy");
|
||||
Event Chatter_FoundBombPlace = ("theres_the_bomb", "theres_the_bomb2");
|
||||
Event Chatter_WhereIsTheBomb = ("wheres_the_bomb", "wheres_the_bomb2", "wheres_the_bomb3", "where_is_it");
|
||||
Event Chatter_DefendingBombSite = ("bombsite", "bombsite2", "im_camping_b", "heading_to_c");
|
||||
Event Chatter_BarelyDefused = ("i_wasnt_worried_for_a_minute", "that_was_a_close_one", "well_done", "whew_that_was_close");
|
||||
Event Chatter_NiceshotCommander = ("good_one_sir", "good_one_sir2", "nice_shot_sir", "nice_one_sir");
|
||||
Event Chatter_NiceshotPall = ("good_one", "good_one2", "nice_shot", "nice_shot2", "good_shot", "good_shot2", "nice", "nice2", "very_nice");
|
||||
Event Chatter_GoingToGuardHostages = ("camping_hostages", "im_going_to_camp_the_hostages", "im_going_to_guard_the_hostages", "im_going_to_guard_the_hostages2");
|
||||
Event Chatter_GoingToGuardDoppedBomb = ("im_going_to_guard_the_bomb", "im_going_to_guard_the_bomb2", "im_going_to_keep_an_eye_on_the_bomb", "im_going_to_watch_the_bomb");
|
||||
Event Chatter_OnMyWay = ("on_my_way", "on_my_way2", "im_coming", "hang_on_im_coming", "be_right_there");
|
||||
Event Chatter_LeadOnSir = ("lead_on_sir", "lead_the_way_sir", "lead_the_way", "ok_sir_lets_go", "lead_on_commander", "lead_the_way_commander", "ok_cmdr_lets_go");
|
||||
Event Chatter_Pinned_Down = ("they_got_me_pinned_down_here", "im_pinned_down");
|
||||
Event Chatter_GottaFindTheBomb = ("theres_the_bomb", "theres_the_bomb2");
|
||||
Event Chatter_Lost_The_Commander = ("weve_lost_the_commander", "the_commander_is_down", "the_commander_is_down_repeat");
|
||||
Event Chatter_CoverMe = ("cover_me", "cover_me2");
|
||||
Event Chatter_BombSiteSecured = ("i_wasnt_worried_for_a_minute", "that_was_a_close_one", "well_done", "whew_that_was_close");
|
||||
29
cfg/addons/yapb/conf/difficulty.cfg
Normal file
29
cfg/addons/yapb/conf/difficulty.cfg
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: difficulty.cfg
|
||||
;
|
||||
; Configuration file contains some difficulty definitions for bots
|
||||
; difficulty selection.
|
||||
;
|
||||
; Format:
|
||||
; Expret = 0.1,0.2,100,100,100
|
||||
;
|
||||
; As like:
|
||||
; Level = minReactionTime(s),maxReactionTime(s),headshotProbability,seenThruWallChance,heardThruWallChance
|
||||
;
|
||||
; Where:
|
||||
; minReactionTime - Minimal time in seconds from time the bot first saw enemy and time he can recognize it.
|
||||
; maxReactionTime - Same as above, but upper cap of the limit.
|
||||
; headshotProbability - Probability bot should aim at head instead of body if body and head both visible.
|
||||
; seenThruWallChance - Chance the bot will attack enemy if he believes he's there and just seen him.
|
||||
; heardThruWallChance - Chance the bot will attack enemy if he believes he's there and just heard him.
|
||||
;
|
||||
|
||||
Noob = 0.8, 1.0, 5, 0, 0
|
||||
Easy = 0.6, 0.8, 30, 10, 10
|
||||
Normal = 0.4, 0.6, 50, 30, 40
|
||||
Hard = 0.2, 0.4, 75, 60, 70
|
||||
Expert = 0.1, 0.2, 100, 90, 90
|
||||
|
||||
826
cfg/addons/yapb/conf/lang/chs_lang.cfg
Normal file
826
cfg/addons/yapb/conf/lang/chs_lang.cfg
Normal file
|
|
@ -0,0 +1,826 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: chs_lang.cfg
|
||||
;
|
||||
; Configuration file contains Simplified Chinese translation for bots menus and messages.
|
||||
;
|
||||
|
||||
[ORIGINAL]
|
||||
\yMain Menu\w
|
||||
|
||||
1. Control Bots
|
||||
2. Features
|
||||
|
||||
3. Fill Server
|
||||
4. End Round
|
||||
|
||||
0. Exit
|
||||
|
||||
|
||||
[TRANSLATED]
|
||||
|
||||
\yYaPB 主菜单\w
|
||||
|
||||
1. YaPB 控制
|
||||
2. 特性
|
||||
|
||||
3. 填充服务器
|
||||
4. 结束本局
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Features\w
|
||||
|
||||
1. Weapon Mode Menu
|
||||
2. Waypoint Menu
|
||||
3. Select Personality
|
||||
|
||||
4. Toggle Debug Mode
|
||||
5. Command Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB 特性\w
|
||||
|
||||
1. 武器模式菜单
|
||||
2. 路点菜单
|
||||
3. 选择个性
|
||||
|
||||
4. 切换调试模式
|
||||
5. 命令菜单
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Control Menu\w
|
||||
|
||||
1. Add a Bot, Quick
|
||||
2. Add a Bot, Specified
|
||||
|
||||
3. Remove Random Bot
|
||||
4. Remove All Bots
|
||||
|
||||
5. Remove Bot Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB 控制菜单\w
|
||||
|
||||
1. 快速添加一个 bot
|
||||
2. 添加一个特定的 bot
|
||||
|
||||
3. 随机删除一个 bot
|
||||
4. 删除所有 bot
|
||||
|
||||
5. 删除 bot 菜单
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Weapon Mode\w
|
||||
|
||||
1. Knives only
|
||||
2. Pistols only
|
||||
3. Shotguns only
|
||||
4. Machine Guns only
|
||||
5. Rifles only
|
||||
6. Sniper Weapons only
|
||||
7. All Weapons
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBots 武器模式\w
|
||||
|
||||
1. 只用刀
|
||||
2. 只用手枪
|
||||
3. 只用霰弹枪
|
||||
4. 只用机枪
|
||||
5. 只用步枪
|
||||
6. 只用狙击枪
|
||||
7. 所有武器
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Personality\w
|
||||
|
||||
1. Random
|
||||
2. Normal
|
||||
3. Aggressive
|
||||
4. Defensive
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB 个性\w
|
||||
|
||||
1. 随机
|
||||
2. 正常
|
||||
3. 进攻型
|
||||
4. 防守型
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Difficulty Level\w
|
||||
|
||||
1. Newbie
|
||||
2. Average
|
||||
3. Normal
|
||||
4. Professional
|
||||
5. Godlike
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB 技能\w
|
||||
|
||||
1. 新手
|
||||
2. 一般
|
||||
3. 高级
|
||||
4. 专业
|
||||
5. 作弊者
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect a team\w
|
||||
|
||||
1. Terrorist Force
|
||||
2. Counter-Terrorist Force
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y选择一个队伍\w
|
||||
|
||||
1. 恐怖分子
|
||||
2. 反恐精英
|
||||
|
||||
5. 自动选择
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y选择一个外观\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. 自动选择
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y选择一个外观\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. 自动选择
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 1)\w
|
||||
|
||||
1. Show/Hide waypoints
|
||||
2. Cache waypoint
|
||||
3. Create path
|
||||
4. Delete path
|
||||
5. Add waypoint
|
||||
6. Delete waypoint
|
||||
7. Set Autopath Distance
|
||||
8. Set Radius
|
||||
|
||||
9. Next...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y路点菜单 (第 1 页)\w
|
||||
|
||||
1. 显示/隐藏路点
|
||||
2. 缓存路点
|
||||
3. 建立路径
|
||||
4. 删除路径
|
||||
5. 添加路点
|
||||
6. 删除路点
|
||||
7. 设置自动路径距离
|
||||
8. 设置路点作用范围
|
||||
|
||||
9. 下一页...
|
||||
|
||||
0. 退出
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 2)\w
|
||||
|
||||
1. Waypoint stats
|
||||
2. Autowaypoint on/off
|
||||
3. Set flags
|
||||
4. Save waypoints
|
||||
5. Save without checking
|
||||
6. Load waypoints
|
||||
7. Check waypoints
|
||||
8. Noclip cheat on/off
|
||||
|
||||
9. Previous...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y路点菜单 (第 2 页)\w
|
||||
|
||||
1. 路点统计
|
||||
2. 自动放置路点开/关
|
||||
3. 设置路点属性
|
||||
4. 保存路点
|
||||
5. 不检查保存路点
|
||||
6. 读取路点
|
||||
7. 检查路点
|
||||
8. 穿墙模式开/关
|
||||
|
||||
9. 上一页...
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Radius\w
|
||||
|
||||
1. SetRadius 0
|
||||
2. SetRadius 8
|
||||
3. SetRadius 16
|
||||
4. SetRadius 32
|
||||
5. SetRadius 48
|
||||
6. SetRadius 64
|
||||
7. SetRadius 80
|
||||
8. SetRadius 96
|
||||
9. SetRadius 128
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y路点作用范围\w
|
||||
|
||||
1. 0
|
||||
2. 8
|
||||
3. 16
|
||||
4. 32
|
||||
5. 48
|
||||
6. 64
|
||||
7. 80
|
||||
8. 96
|
||||
9. 128
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Type\w
|
||||
|
||||
1. Normal
|
||||
\r2. Terrorist Important
|
||||
3. Counter-Terrorist Important
|
||||
\w4. Block with hostage / Ladder
|
||||
\y5. Rescue Zone
|
||||
\w6. Camping
|
||||
7. Camp End
|
||||
\r8. Map Goal
|
||||
\w9. Jump
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y路点类型\w
|
||||
|
||||
1. 正常
|
||||
\r2. 恐怖分子重要点
|
||||
3. 反恐精英重要点
|
||||
\w4. 人质无法通过/梯子
|
||||
\y5. 人质解救点
|
||||
\w6. 守卫点
|
||||
7. 守卫结束角度
|
||||
\r8. 地图目标点
|
||||
\w9. 跳跃点
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Flags\w
|
||||
|
||||
\yAdd waypoint flag:\w
|
||||
|
||||
1. Block with Hostage
|
||||
2. Terrorists Specific
|
||||
3. CTs Specific
|
||||
4. Use Elevator
|
||||
|
||||
\yDelete waypoint flag:\w
|
||||
|
||||
5. Block with Hostage
|
||||
6. Terrorists Specific
|
||||
7. CTs Specific
|
||||
8. Use Elevator
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y路点属性\w
|
||||
|
||||
\y添加路点属性:\w
|
||||
|
||||
1. 人质无法通过
|
||||
2. 恐怖分子
|
||||
3. 反恐精英
|
||||
4. 使用电梯
|
||||
|
||||
\y删除路点属性:\w
|
||||
|
||||
5. 人质无法通过
|
||||
6. 恐怖分子
|
||||
7. 反恐精英
|
||||
8. 使用电梯
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yBot Command Menu\w
|
||||
|
||||
1. Make Double Jump
|
||||
2. Finish Double Jump
|
||||
|
||||
3. Drop the C4 Bomb
|
||||
4. Drop the Weapon
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBot 命令菜单\w
|
||||
|
||||
1. 双跳跃
|
||||
2. 双跳跃结束
|
||||
|
||||
3. 扔掉炸弹
|
||||
4. 扔掉枪
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yAutoPath Distance\w
|
||||
|
||||
1. Distance 0
|
||||
2. Distance 100
|
||||
3. Distance 130
|
||||
4. Distance 160
|
||||
5. Distance 190
|
||||
6. Distance 220
|
||||
7. Distance 250 (Default)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y自动路径距离\w
|
||||
|
||||
1. 0
|
||||
2. 100
|
||||
3. 130
|
||||
4. 160
|
||||
5. 190
|
||||
6. 220
|
||||
7. 250 (默认)
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
\yCreate Path (Choose Direction)\w
|
||||
|
||||
1. Outgoing Path
|
||||
2. Incoming Path
|
||||
3. Bidirectional (Both Ways)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\y建立路径 (选择方向)\w
|
||||
|
||||
1. 向外
|
||||
2. 向内
|
||||
3. 双向
|
||||
|
||||
0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
Map not waypointed. Can't Create Bot
|
||||
|
||||
[TRANSLATED]
|
||||
没有路点。不能建立 bot
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints has been changed. Load waypoints again...
|
||||
|
||||
[TRANSLATED]
|
||||
路点已经改变。需要重新读取路点...
|
||||
|
||||
[ORIGINAL]
|
||||
Invalid skill given. Using random skill.
|
||||
|
||||
[TRANSLATED]
|
||||
输入了不正确的技能值。使用随机技能。
|
||||
|
||||
[ORIGINAL]
|
||||
Connecting Bot...
|
||||
|
||||
[TRANSLATED]
|
||||
正在连接 Bot...
|
||||
|
||||
[ORIGINAL]
|
||||
Fill Server with %s bots...
|
||||
|
||||
[TRANSLATED]
|
||||
用 %s bot 来填充服务器...
|
||||
|
||||
[ORIGINAL]
|
||||
Bots are removed from server.
|
||||
|
||||
[TRANSLATED]
|
||||
Bot 已被从服务器删除。
|
||||
|
||||
[ORIGINAL]
|
||||
Bot '%s' kicked
|
||||
|
||||
[TRANSLATED]
|
||||
Bot '%s' 已被删除。
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Remove Menu (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. Back
|
||||
|
||||
[TRANSLATED]
|
||||
\y删除 bot (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. 退出
|
||||
|
||||
[ORIGINAL]
|
||||
%s\d %1.1d. Not a Bot\w
|
||||
|
||||
[TRANSLATED]
|
||||
%s\d %1.1d. 不是 Bot\w
|
||||
|
||||
[ORIGINAL]
|
||||
9. More...
|
||||
|
||||
[TRANSLATED]
|
||||
9. 更多...
|
||||
|
||||
[ORIGINAL]
|
||||
All Bots died !
|
||||
|
||||
[TRANSLATED]
|
||||
所有的 bot 已被删除。
|
||||
|
||||
[ORIGINAL]
|
||||
%s weapon mode selected
|
||||
|
||||
[TRANSLATED]
|
||||
%s 武器模式已被选定。
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Source Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
错误: 寻找路径源不正确->%d
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Destination Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
错误: 寻找路径目标不正确->%d
|
||||
|
||||
[ORIGINAL]
|
||||
Denied path creation from %d to %d (path already exists)
|
||||
|
||||
[TRANSLATED]
|
||||
无法建立从 %d 到 %d 的路径 (路径已存在)
|
||||
|
||||
[ORIGINAL]
|
||||
Path added from %d to %d
|
||||
|
||||
[TRANSLATED]
|
||||
从 %d 到 %d 的路径已添加
|
||||
|
||||
[ORIGINAL]
|
||||
This is not Camping Waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
没有守卫路点
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint number out of range (Valid range From 0 to %d)
|
||||
|
||||
[TRANSLATED]
|
||||
路点编号超出范围 (合法的范围从 0 到 %d)
|
||||
|
||||
[ORIGINAL]
|
||||
Cannot connect waypoint to itself
|
||||
|
||||
[TRANSLATED]
|
||||
无法将路点与自身连接
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d connected with invalid Waypoint Nr. %d!
|
||||
|
||||
[TRANSLATED]
|
||||
路点 %d 与非法的路点 %d 连接!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d isn't connected with any other Waypoint!
|
||||
|
||||
[TRANSLATED]
|
||||
路点 %d 没有和其它任何路点连接!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d pathnumber differs from index!
|
||||
|
||||
[TRANSLATED]
|
||||
路点 %d 路径编号不等于索引号!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d Camp-Endposition not set!
|
||||
|
||||
[TRANSLATED]
|
||||
路点 %d 守卫结束角度没有设定!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set a Rescue Point!
|
||||
|
||||
[TRANSLATED]
|
||||
你没有设置一个人质解救点!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Terrorist Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
你没有设置一个 T 重要路点!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any CT Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
你没有设置一个 CT 重要路点!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Goal Point!
|
||||
|
||||
[TRANSLATED]
|
||||
你没有设置一个目标点!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint Nr. 0 to Waypoint Nr. %d!
|
||||
|
||||
[TRANSLATED]
|
||||
从路点 #0 到路点 #%d 的路径损坏!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint Nr. %d to Waypoint Nr. 0!
|
||||
|
||||
[TRANSLATED]
|
||||
从路点 #%d 到路点 #%0 的路径损坏!
|
||||
|
||||
[ORIGINAL]
|
||||
Choose weapon from 1 to 7 range
|
||||
|
||||
[TRANSLATED]
|
||||
选择武器,范围从 1 到 7
|
||||
|
||||
[ORIGINAL]
|
||||
All dead bots will vote for map #%d
|
||||
|
||||
[TRANSLATED]
|
||||
所有的死亡的 bot 将会投地图 #%d 的票
|
||||
|
||||
[ORIGINAL]
|
||||
Bot %s executing command %s
|
||||
|
||||
[TRANSLATED]
|
||||
Bot %s 正在执行命令 %s
|
||||
|
||||
[ORIGINAL]
|
||||
Player is NOT Bot!
|
||||
|
||||
[TRANSLATED]
|
||||
玩家不是一个 bot!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
路点编辑已打开
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
路点编辑已关闭
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
穿墙模式已打开
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
路点已关闭
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
路点已打开
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
穿墙模式已关闭
|
||||
|
||||
[ORIGINAL]
|
||||
Showing Direction to Waypoint #%d
|
||||
|
||||
[TRANSLATED]
|
||||
显示到路点 #%d 的方向
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints Saved
|
||||
|
||||
[TRANSLATED]
|
||||
路点已保存
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints loaded
|
||||
|
||||
[TRANSLATED]
|
||||
路点已读取
|
||||
|
||||
[ORIGINAL]
|
||||
Nodes work Fine
|
||||
|
||||
[TRANSLATED]
|
||||
路点没有错误
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Nr. %d now cached
|
||||
|
||||
[TRANSLATED]
|
||||
路点 #%d 已被缓存
|
||||
|
||||
[ORIGINAL]
|
||||
Player '%s' teleported to waypoint #%d (x:%d, y:%d, z:%d)
|
||||
|
||||
[TRANSLATED]
|
||||
玩家 '%s' 已被传送到路点 #%d (x:%d, y:%d, z:%d)
|
||||
|
||||
[ORIGINAL]
|
||||
Experience tab saved
|
||||
|
||||
[TRANSLATED]
|
||||
经验已保存
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
经验已打开
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
经验已关闭
|
||||
|
||||
[ORIGINAL]
|
||||
Command not supported on dedicated server
|
||||
|
||||
[TRANSLATED]
|
||||
此命令无法在独立的服务器上使用
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint not saved
|
||||
There are errors, see console
|
||||
|
||||
[TRANSLATED]
|
||||
路点没有被保存
|
||||
有错误,详见控制台
|
||||
|
||||
[ORIGINAL]
|
||||
There are errors, see console
|
||||
|
||||
[TRANSLATED]
|
||||
有错误,详见控制台
|
||||
|
||||
[ORIGINAL]
|
||||
You're dead, and have no access to this menu
|
||||
|
||||
[TRANSLATED]
|
||||
你已死亡,不能使用此菜单
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath disabled
|
||||
|
||||
[TRANSLATED]
|
||||
自动路径已关闭
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath maximum distance set to %f
|
||||
|
||||
[TRANSLATED]
|
||||
最大自动路径距离已被设为 %f
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find nearest waypoint in 50 units
|
||||
|
||||
[TRANSLATED]
|
||||
在最近的 50 单位内无法找到一个路点
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find destination waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
无法找到目标路点
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to connect waypoint with itself
|
||||
|
||||
[TRANSLATED]
|
||||
无法将路点与自身连接
|
||||
|
||||
[ORIGINAL]
|
||||
There is already no path on this waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
此路点已经没有路径
|
||||
|
||||
[ORIGINAL]
|
||||
Cached waypoint cleared (nearby point not found in 50 units range)
|
||||
|
||||
[TRANSLATED]
|
||||
缓存的路点已清除 (在 50 单位的范围内没有找到路点)
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint #%d has been put into memory
|
||||
|
||||
[TRANSLATED]
|
||||
路点 #%d 已被放入内存
|
||||
|
||||
[ORIGINAL]
|
||||
Maximum players reached (%d/%d). Unable to create Bot.
|
||||
|
||||
[TRANSLATED]
|
||||
最大的玩家数目已达到 (%d/%d)。无法添加 bot。
|
||||
571
cfg/addons/yapb/conf/lang/de_chat.cfg
Normal file
571
cfg/addons/yapb/conf/lang/de_chat.cfg
Normal file
|
|
@ -0,0 +1,571 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: de_chat.cfg
|
||||
;
|
||||
; Configuration file contains German translation for bot chats.
|
||||
;
|
||||
|
||||
[BOMBPLANT]
|
||||
Jeeesuzzz, nicht schon wieder !
|
||||
Komm schon %t, lass uns die Bombe suchen!
|
||||
Die kleine C4 wird doch wohl nicht hochgehen?
|
||||
Jetzt schlaegts dreizehn! Wie konnte das passieren man %t?
|
||||
Wenn sie entschaerft ist geb ich einen aus %t!
|
||||
Schon wieder ihr verdammten Schlafmuetzen!
|
||||
Wenn sie hochgeht entfaellt Deine Schichtzulage mensch!
|
||||
Letztes Mal hat's nur 5 Sekunden bis zum entschaerfen gedauert...
|
||||
Kennst Du noch die FATBOY %t? die hat RUMS gemacht!
|
||||
Die Ts fangen an mich zu nerven
|
||||
BOOOOMMMMM!!! hehe
|
||||
Ist ne schmutzige Bombe hab ich gehoert- also sei vorsichtig %t
|
||||
Ich hab doch gesagt Ihr sollt da besser aufpassen %t!LOS!
|
||||
Beeil Dich besser %t
|
||||
Wenn sie vorher hochgeht %t- ich sag Deiner Frau bescheid
|
||||
Sitzt da noch irgendwo ein T an der Bombe?
|
||||
Ich hoffe der Entschaerfungs-Lehrgang hat was genuetzt %t
|
||||
Sag schon, ist es das rote oder das blaue Kabel ?
|
||||
%t wir sollten langsam mal entschaerfen gehen...
|
||||
Bombe entschaerfen gibt Extrazulage hab ich gehoert %t
|
||||
Ob sie diesmal mit Naegeln gefuellt ist?
|
||||
Mal sehen wie mein neues Entschaerfungskit funktioniert...
|
||||
Wenn es Plastiksprengstoff ist hau lieber ab %t
|
||||
Die Anleitung zum Bombenbauen haben sie bestimmt aus dem Internet...
|
||||
...Und mein Herz macht Boooom *grins*
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Messages after killing somebody:
|
||||
// Minimum Number is 1
|
||||
// For the %v the name of the victim will
|
||||
// be inserted
|
||||
//
|
||||
[KILLED]
|
||||
%v, du kannst dich nicht mit mir vergleichen !
|
||||
Tschuldigung, %v. Du standst in meinem Weg.
|
||||
Du bist ganz gut geflogen, %v.
|
||||
Manman keine Uebersicht %v
|
||||
Dreh mir naechstes mal nicht den Hintern zu %v
|
||||
WOOOW %v
|
||||
Guck mal auf Dein Radar %v
|
||||
Du konntest das mal besser %v
|
||||
Red Dich nicht schon wieder mit schlechtem Ping raus %v
|
||||
So eine Waffe hat auch einen Abzug %v
|
||||
Hast Du ne Ahnung was Dich da getroffen hat %v?
|
||||
Bind Dir naechstes mal die Schnuersenkel zu %v
|
||||
Ich musste es tun, %v. Du verstehst schon...
|
||||
hehe ein leichtes Ziel %v
|
||||
Mach das nie wieder hehe %v
|
||||
OWNEEED %v
|
||||
Jawooolll!
|
||||
Wie Du es verdienst %v
|
||||
Vielleicht haettest Du Zielen sollen %v
|
||||
Machs mir naechstes mal bitte etwas schwerer %v
|
||||
Du haettest rennen sollen, als du noch konntest, %v.
|
||||
Ich war immer besser, %v. Immer.
|
||||
Jaja, jetzt kommt wieder: WAR DAS LAG *gg
|
||||
Es ist immer die linke Maustaste %v
|
||||
Naja Zielen ueben wir nochmal %v
|
||||
Hast Du mich eigentlich gesehen %v?
|
||||
Immer noch nichts gelernt %v?
|
||||
Nochmal zurueck auf den Schiesstand Du nap %v
|
||||
Ich wette du hasst es wenn das passiert, oder %v?
|
||||
Das wird dich lehren, %v !
|
||||
Hey, komm schon %v! Diesmal hast du mich beinahe getroffen !
|
||||
Ha...ha!
|
||||
Du bist Nichts, %v. Gar nichts .
|
||||
%v haettest Du nicht an haette ich auch nicht an ;-)
|
||||
%v ich mache mir Sorgen um dich...
|
||||
Du solltest mal ein bisschen ueben %v
|
||||
Tschuldige %v, mein Kopfschuss Script is besser als deins.
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Chat Messages when bot connects to server
|
||||
// !!Minimum Number is 1!!
|
||||
[WELCOME]
|
||||
Hi Leute :)
|
||||
Wazzzzup?
|
||||
Moin moin wie gehts?
|
||||
Gruess Gott miteinander ;-)
|
||||
Hi, alles fit bei Euch?
|
||||
Hoi, man bin ich mueede
|
||||
Hallo, ich hoffe heit treff ich auch mal was...
|
||||
Hallloooo alle zusammen!
|
||||
Oh man hier gibts doch bestimmt keine Cheater, oder?
|
||||
Hi, alle Cheater verlassen jetzt bitte den Server
|
||||
Hoooiiii
|
||||
Man endlich ein Slot frei!
|
||||
Du meine Guete sind hier viele Cheater...
|
||||
Moin alle machen jetzt bitte Ihren Aimbot aus hehe!
|
||||
//
|
||||
// Chat Messages when dead and bored
|
||||
// !!Minimum Number is 9!!
|
||||
//
|
||||
[DEADCHAT]
|
||||
Es macht mich krank diese Idioten anzugucken.
|
||||
Es ist Zeit die Map zu wechseln, oder ?
|
||||
%t GO,GO,GO!!
|
||||
Die Camper Loser !
|
||||
Mir ist sooo langweilig !
|
||||
Ich kann nicht glauben das %f NICHT cheatet !
|
||||
Zugucken ist scheisse...
|
||||
Wieso immer ich??
|
||||
Das ist unfair
|
||||
Der hatte doch AN!
|
||||
Boah ich kann wenigstens verlieren!
|
||||
Ich wuenschte bessere Leute wuerden den Server joinen.
|
||||
Das sah schmerzhaft aus.
|
||||
Alles Noobs man!
|
||||
Ey man ich hab bald kein Bock mehr!
|
||||
Es macht heute Spass...
|
||||
Noch %r in dieser Runde und ich gucke schon zu :(
|
||||
Warum versuchen alle immer mich zu killen :)
|
||||
Besucht http://www.geocities.com/countfloyd_1999/
|
||||
Mein Handgelenk tut schon weh...
|
||||
Diese Map ist scheisse...
|
||||
Das LAG ist Schuld!
|
||||
Ich hab 'nen schlechten Tag heute.
|
||||
%r und %t ist immer noch am Leben ! Irgendwas ist hier falsch...
|
||||
Werden die bald aufhoeren zu campen ? Nur noch %r !!
|
||||
Ich bin besser in Quake 3, das ist schon mal sicher!
|
||||
Nur noch %r in dieser Runde...
|
||||
Botman muss sooo cool sein...
|
||||
Daemliche Bots!
|
||||
Guck dir diese Idioten an !!!
|
||||
Ich wette %t schaffts nicht zu ueberleben
|
||||
Ich bin heute so verdammt muede...
|
||||
Ich sollte wirklich in's Bett gehen.
|
||||
Mach mal ne andere Map an!
|
||||
Normalerweise spiel ich nicht so schlecht !
|
||||
Bitte kein %m mehr !
|
||||
Ich hasse %m, wirklich :(
|
||||
Snipern ist alles was die koennen.
|
||||
Habt ihr mich fliegen sehen?
|
||||
LOL! Guck dir %t an!
|
||||
Das lag alles nur am LAG!!
|
||||
Voted fuer 'nen Mapchange, bitte !
|
||||
Ist schon einer der Bots wieder steckengeblieben ?
|
||||
Boooooom !!! *lol*
|
||||
Insane in the membrane, hehe!
|
||||
Ich bin mir sicher der Kerl benutzt 'nen Aimbot !
|
||||
HEY %f DU VERDAMMTER CHEATER!!!
|
||||
Sind Bots hier im Spiel ?
|
||||
Wuerdest du mir dein Kopfschuss Script geben ?
|
||||
Naechste Runde sollten wir zusammenbleiben.
|
||||
Bekiffte Teamkiller ueberall!!!
|
||||
Boah guck dir %fs Statistik an !!
|
||||
Wozu gibt's eigentlich Clans ? Kapier ich nicht.
|
||||
Kennt ihr Jumbot ? Ist echt geil!
|
||||
Immer diese Bots!
|
||||
Wenn Botman cool ist, was ist dann erst TheFatal ?
|
||||
Ich hab ein beschissenes Lag gerade.
|
||||
Mein Fastpath hat sich verschluckt glaube ich
|
||||
Ich finde NNBot ist um einiges besser als Realbot...
|
||||
Schade das der Android Bot so langsam geupdated wird.
|
||||
Ich mache 'ne Zigaretten Pause...
|
||||
Warum haben die die Fahrzeuge in Cs reingemacht ?
|
||||
Das ist doch voll langweilig
|
||||
Nicht schon wieder die Bots!
|
||||
Ich musste nachladen und der Penner schiesst mir in den Kopf!
|
||||
Mehr Speed durch hoehere Geschwindigkeit!
|
||||
Ich muss noch an meinen Reaktionen feilen
|
||||
Wenn das Captain Kirk gesehen haette!
|
||||
Ich war so kurz davor!
|
||||
Fast ware mein Plan aufgegangen!
|
||||
|
||||
[REPLIES]
|
||||
|
||||
|
||||
@KEY "AIMBOT", "WALLHACK"
|
||||
%s, woher willst du das wissen ?
|
||||
Sogar VAC2 erkennt nicht alles...
|
||||
Du kannst im Moment echt nicht sicher sein ob einer cheatet oder gut spielt
|
||||
Halts Maul %s, Aimbots sind cool!
|
||||
Wallhacks sind ein Werk des Teufels :)
|
||||
HLGuard ist ganz gut (www.unitedadmins.com)
|
||||
VAC2 bringt auch nicht so viel
|
||||
Wer wirklich cheaten will kann das auch leider -so war es immer
|
||||
An den Netsettings drehen ist doch auch cheaten
|
||||
An Fairplay denkt niemand mehr
|
||||
Ich spiel nur noch mit meinen Kumpels- da weiss ich dass die nicht an haben
|
||||
Cheaten ist doch langweilig nach ner halben Stunde
|
||||
Manche koennen eben nicht verlieren...
|
||||
Haben diese Bots hier eigentlich an? LOL
|
||||
Erzaehl keinen Scheiss- ich hab nicht an!!
|
||||
Mein Wallhack ist besser als Deiner
|
||||
Ich hab gehoert bei diesem Polen gibts private Cheats billiger...
|
||||
Cheaten ist nur was fuer Looser!
|
||||
|
||||
@KEY "ANDROID"
|
||||
*seufz* achja das waren noch Zeiten...
|
||||
%s war das auch dein erster Bot ?
|
||||
Weiss einer was DaTa jetzt macht ?
|
||||
Man kann %m nicht mit Android spielen, oder ?
|
||||
|
||||
@KEY "BOTMAN"
|
||||
Wer ist dieser Botman ueber den alle reden???
|
||||
Besucht doch mal seine Seite unter www.planethalflife.com/botman/
|
||||
Ohne seinen SourceCode wuerden viele andere Bots gar nicht existieren!
|
||||
Ich bin gespannt wann HPB-Bot fertig ist...
|
||||
Hast du schon mit seinem HPB-Bot gespielt ?
|
||||
Mit dem Darkulator von Botman korrigiere ich zu dunkle Custommaps
|
||||
Seine Seite ist auch auf http://bots-united.com
|
||||
|
||||
@KEY "BOT ", "BOTS"
|
||||
Warum redet ihr immer darueber ?
|
||||
Es sind keine Bots auf diesem Server %s, ich schwoer's!
|
||||
Bots sind cool!!!
|
||||
Welcher ist dein Lieblingsbot %s?
|
||||
Falls ihr euren eigenen programmieren wollt, fragt doch ma Botman!
|
||||
Bots, immer nur Bots - ihr solltet ma gegen menschliche Gegner spielen..
|
||||
Die meisten Bots sind immer noch saudumm...
|
||||
|
||||
@KEY "CAMPER", "CAMPING"
|
||||
Echt, ich hasse diese Camper!
|
||||
Camping sucks!
|
||||
Campst du nicht auch manchmal %s ?
|
||||
Man immer diese Camperei...
|
||||
Campen ist fuer manche die einzige Moeglichkeit zu gewinnen
|
||||
Ja, gutes altes Camper-Strike...
|
||||
Guckst Du auch immer DIE CAMPER?
|
||||
Nee GUCKST DU Camper da hinten!
|
||||
Wer ist eigentlich der Erfinder des Campings?
|
||||
Ab und zu ist ja noch o.k.
|
||||
Die CTs an der Bombe sollen doch campen!
|
||||
Wieso campen die Ts immer bei den Hossies?
|
||||
|
||||
@KEY "CHEAT", "VAC", "VAC2"
|
||||
Diese verdammten Cheater ruinieren das ganze Spiel!
|
||||
I glaube das %f cheatet
|
||||
I hasse cheater!
|
||||
Cheating sux!
|
||||
Warum cheaten so nur viele ?
|
||||
Punkbuster koennte helfen...
|
||||
Spielt mit Bots - die cheaten nicht!
|
||||
Trotz Vac cheaten immer so viele!
|
||||
Ich dachte seit VAC2 kann niemand mehr cheaten :p
|
||||
|
||||
@KEY "CLAN"
|
||||
Was sind den Clans ?
|
||||
Ich war ma in nem Clan, aber das war voll scheisse.
|
||||
Aus welchem Clan bist du, %s?
|
||||
Clans sind doch voll der Unsinn EY!
|
||||
Endlich gehoer ich irgendwo dazu!
|
||||
Eh %s willst du unsern Clan joinen?
|
||||
Ich bin voll stolz auf meinen Clan!
|
||||
In nem Clan zu spielen ist was fuer Leute die nie rauskommen...
|
||||
Unser Clanleader wollte immer dass wir cheaten bei Ligaspielen
|
||||
Mein Clan hat sich letzte Woche aufgeloest
|
||||
|
||||
@KEY "CS", "CSS", "CS:S" "COUNTERSTRIKE", "COUNTER-STRIKE", "CSTRIKE"
|
||||
Counter-Strike wird langsam langweilig...
|
||||
%s wie lange spielst du schon CS ?
|
||||
CS ist immer noch der beliebteste Online-Shooter
|
||||
Ich spiel CS seit der ersten Beta!
|
||||
Auch BF2 konnte CS nicht vom Thron stossen
|
||||
Zu viele Newbies spielen's jetzt
|
||||
Die Source-Version sieht schon richtig gut aus!
|
||||
Bin gespannt ob es irgendwann ein beliebteren Shooter gibt als CS
|
||||
Zuviele Leute die CS spielen cheaten jetzt
|
||||
CS:S laeuft nicht richtig auf meiner alten Kiste :-(
|
||||
Macht nicht mehr so viel Spass wie frueher
|
||||
|
||||
@KEY "DOD", "DOD:S", "DAY OF DEFEAT"
|
||||
Ich verstehe nicht was Leute an DoD gut finden
|
||||
CS rult total ab, mann wie das rult das gibts nich!
|
||||
%s meinst du es koennte so bekannt werden wie CS ?
|
||||
%s findest DoD besser als CS ?
|
||||
Day of Defeat ist scheisse find ich.
|
||||
Die Source-Version ist viel besser!
|
||||
|
||||
@KEY "ENGINE"
|
||||
Ich hab ma gehoert die HL Engine ist son Zwischending zwischen Q1 und Q2, komisch wah?
|
||||
%s vermisst du nicht die Zeiten als ne Engine noch ne Software Engine war ?
|
||||
Die HL Engine ist immer noch gut, trotz ihres Alters...
|
||||
Mach doch selber ne engine %s !
|
||||
Engine ist egal solange das Spiel Spass macht!
|
||||
Ich mag nur Spiele mit der neuesten Engine- Eyecandy forever!
|
||||
Scheiss auf die Engine hauptsache mein WH geht.
|
||||
Die Source-Engine ist ja wohl sowas von Endgeil!
|
||||
Die neue Quake-Engine ist noch langsamer als Source
|
||||
|
||||
@KEY "FUCK", "FICK", "PISS", "VERDAMMT", "KOTZ", "SCHISS", "SCHEISS"
|
||||
Verflucht noch mal, hoer auf zu fluchen, %s!
|
||||
Das finde ich widerlich und ekelhaft, %s!
|
||||
Wo hast du nur diese Woerter her, %s?
|
||||
Ja, du hast Recht, %s. Aber JETZT HALT DIE KLAPPE!
|
||||
Pass auf, was du sagst, %s!
|
||||
%s, sag das nie wieder - das is unhoeflich!
|
||||
|
||||
@KEY "HEHE", "HAHA", "LOL", ":)", "SPASS"
|
||||
Ich bin froh, dass wenigstens du deinen Spass hast, %s...
|
||||
Geniesse es, solange du es noch kannst, %s!
|
||||
Ja, sehr witzig, %s...
|
||||
Der war gut, %s
|
||||
|
||||
@KEY "IMMER"
|
||||
Nicht immer %s !
|
||||
Ich finds gut ;)
|
||||
Komm schon %s, das war erst das zweite Mal!
|
||||
|
||||
@KEY "ICH DENKE", "ICH GLAUBE", "ICH SCHAETZE"
|
||||
Du denkst zu viel, %s ;-)
|
||||
Nicht denken ... schiessen mensch!
|
||||
...und ich denke du solltest deine Klappe halten und zocken!
|
||||
Und du glaubst das wirklich, %s?
|
||||
Kennt Ihr Sartre?
|
||||
Wenn ich denken wollte-wuerde ich dann CS spielen?
|
||||
Warum denkst du das?
|
||||
Hast du ICQ %s ?
|
||||
|
||||
@KEY "JOEBOT"
|
||||
Ja, JoeBot iss nich schlecht...
|
||||
Lustigerweise wurde JoeBot erst bekannt als es NNBot nicht mehr gab...
|
||||
Ich wuerde gern wissen wo man Neuronale Netze noch benutzen koennte
|
||||
Also denkst du Joebot rockt total ab oder was ?
|
||||
Ja klar guck mal bei http://bots-united.com
|
||||
|
||||
@KEY "JUMBOT"
|
||||
JB ? War mal gut aber ParaBot ist viel besser jetzt!
|
||||
JB's Vorteil wahr immer das ein MOD war, keine hooking DLL
|
||||
Achja Jumbot von Fatal. Wuerd gern wissen was er jetzt macht.
|
||||
Hab ma gehoert The Fatal macht jetzt Bots fuer AHL ?
|
||||
Der hat doch an Farcry mitgearbeitet nicht?
|
||||
Ist schwer in der Gaming-Industrie Geld zu verdienen
|
||||
Gibt nur wenige Game-Studios in Deutschland
|
||||
|
||||
@KEY "MUSIC", "BAND", "MUSIK"
|
||||
Mir egal so lange es kein kommerzieller Dreck ist
|
||||
Underground Electro Polka iss mein Ding!
|
||||
Benutzt du noch Napster %s ?
|
||||
Hat einer gute MP3 Links ?
|
||||
Pooops I did it again!
|
||||
Metallica forever!
|
||||
Depeche Mode forever!
|
||||
Kennt wer Corvus Corax-dieses Mittelalter-Gedudel?
|
||||
Ich steh auf Techno WUUMS
|
||||
Mein Subwoofer ist groesser als Deiner
|
||||
In meinem GTI ist ne 3000-Watt Anlage- hat mir mein Schwager eingebaut
|
||||
Heavy Metal ist doch Schrott
|
||||
Du hoerst wohl Schlager oder?
|
||||
HOELLEHOEELLEHOEELLLE!!RUMMSTATA
|
||||
Meine Freundin steht auf 80er
|
||||
Ey nee alles ausser Gruft-Mucke
|
||||
Ich hoer nur schwarz
|
||||
Hopper sind goil!
|
||||
Keine Chance den Hoppern!
|
||||
Boah alles Aggro oder was?
|
||||
Man seid Ihr alt! Das ist doch Opa-Mucke alles
|
||||
|
||||
@KEY "NNBOT"
|
||||
Zu schade das NNBot nicht weitergemacht wird...
|
||||
Versuch mal Joebot wenn du NNBot gemocht hast %s
|
||||
%s schon von Ditlews neuem MOD gehoert ?
|
||||
|
||||
@KEY "PARABOT"
|
||||
ParaBot ist der coolste DM Bot mit dem ich je gespielt habe!
|
||||
%s du solltest mal ParaBot ausprobieren, ist richtig geil!
|
||||
Schade das bis jetzt kein CSBot so eine gute Nav hat wie ParaBot
|
||||
Unterstuetzt jetzt schon 3 MODs
|
||||
Gibt auch nen Steam-Patch fuer Parabot und metamod geht auch
|
||||
|
||||
@KEY "PING", "LAG"
|
||||
Ich habe immer nen Ping von 5, hab DSL!!
|
||||
Meine Verbindung ist zum kotzen...
|
||||
Woher kommst du %s ?
|
||||
jaja hinterher war es immer das lag...
|
||||
Bei uns gibts kein DSL
|
||||
Seit DSL und Fastpath geht die LAN-Scene unter
|
||||
Was soll ich auf ner LAN wenns im Internet genauso schnell ist?
|
||||
Abends hat unser Server immer nen schlechten Ping
|
||||
Kennt Ihr nen guten Gameserver-Anbieter?
|
||||
Bin oft mit meinem Laptop nicht online und zocke gegen Bots dann.
|
||||
Wenn alle auf Public mit Aimbot spielen zogge ich lieber gegen Bots.
|
||||
Spiel offline mit Bots wenn deine Verbindung schlecht ist
|
||||
Wechsel ma den Provider %s!
|
||||
|
||||
@KEY "PUNKBUSTER"
|
||||
Don't be a PUNK! (unterstuetzt www.punkbuster.com)
|
||||
Ich lagge immer wenn ich Punkbuster benutze
|
||||
Tony Ray von PB scheint komisch zu sein...
|
||||
Gibts Punkbuster eigentlich noch? Ist doch jetzt VAC oder?
|
||||
Was ist eigentlich mit Cheating-Death?
|
||||
|
||||
@KEY "Q3", "QUAKE"
|
||||
Q3 hat ein schlechtes Lighting IMO
|
||||
Half-Life rult immer noch %s!
|
||||
Schon mal von DMC gehoert %s ? :)
|
||||
Quake 1 FOREVER!
|
||||
Q4 wird kaum online gespielt.
|
||||
Q3 war irgendwie schneller als Q4
|
||||
Ey die Monster in Q4 fand ich voll unheimlich...
|
||||
|
||||
@KEY "HL2", "Half-life2"
|
||||
HDR sieht richtig gut aus!
|
||||
Fuer die neuen Source-maps ist mein Rechner zu lahm
|
||||
HL2 rockt ja wohl total ab!
|
||||
Ich frage mich wer eigentlich der G-man ist?
|
||||
Wann kommt denn Aftermath?
|
||||
Die neuen Games sind mir wurscht-ist doch immer dasselbe
|
||||
HL2 ist ja wohl der Beste Shooter von Welt!
|
||||
|
||||
@KEY "REALBOT"
|
||||
Ist der wenigstens gut ?
|
||||
Ist der RealBot immer noch ohne Wegpunkte ?
|
||||
Hmmm...RB. Der erste wegpunktlose Bot oder ?
|
||||
Habe gehoert das RB jetzt sowas wie ParaBot versucht ?!?
|
||||
Ich hab sie immer liebevoll 'WandKnuddler' genannt ;)
|
||||
Den Realbot gibts auch bei www.bots-united.com
|
||||
|
||||
@KEY "SCRIPT", "SKRIPT"
|
||||
Scripts sind was fuer Verlierer
|
||||
%s du weisst wahrscheinlich nicht mal wie man Tasten bindet ?
|
||||
Wusstest du das sogar Kauf-Skripte als Cheat gelten ?
|
||||
Ich hab Einheizers Script ist voll cool
|
||||
Nein ich meine nicht das No-Recoil-Script
|
||||
Steck Dir Deinen No-Recoil-Kram sonstwo rein
|
||||
|
||||
@KEY "SERVER"
|
||||
Ich bin immer auf diesem Server
|
||||
Meine Freunde und ich spielen oft auf diesem Server
|
||||
Ich finde dieser Server hat ne gute Map Rotation
|
||||
Zuviele noobs auf dem Server
|
||||
Gibts hier eigentlich Custommaps?
|
||||
Was laeuft denn hier fuer ein Anti-Cheat?
|
||||
|
||||
@KEY "SORRY", "SCHULDIGUNG"
|
||||
Ja ja, hinterher sagt jeder dass es ihm Leid tut!
|
||||
Die Ausrede hilft jetzt auch nicht mehr, %s!
|
||||
Kannst Du nicht aufpassen?
|
||||
Beim naechsten Mal erst ueberlegen, dann machen, %s!
|
||||
Es tut mir auch leid!
|
||||
Du glaubst gar nicht wie leid dir das noch tun wird...
|
||||
|
||||
@KEY "PODbot"
|
||||
Es gibt ja einige Podbot-Nachfolger auf http://bots-united.com
|
||||
Die neuen Podbots haben meist einen besseren Waypoint-Editor
|
||||
Fuer Podbot-Waypoints guck mal unter: http://coconut.de.tc
|
||||
YAPB von Whistler finde ich einen guten Podbot-Nachfolger
|
||||
Die meisten Nachfolger laufen auch unter Metamod
|
||||
Joebot hat auch ein paar echt gute Funktionen!
|
||||
|
||||
@KEY "TEAMKILL", "TK"
|
||||
Teamkiller sollten auf diesem Server hier gebannt werden...
|
||||
Wer iss der Teamkiller %s ?
|
||||
Ich mag es alle abzustechen, MWUHAHAHA!!
|
||||
Keine Teamkiller hier!
|
||||
Teamkill ist ja wohl das letzte!
|
||||
Hat dich %t gekillt ? Macht er oefter...
|
||||
Nicht schon wieder...
|
||||
Wo ist der Admin ? Der sollte sich mal darum kuemmern...
|
||||
%s nur noch %r dann kannst du's ihm zurueckzahlen!
|
||||
Sofort kicken und bannen!
|
||||
|
||||
@KEY "MUEDE", "SCHLAF"
|
||||
Geh ins Bett, %s
|
||||
Goenn dir ne Pause, %s...
|
||||
Boah 18 Stunden nonstop- ich kann echt nicht mehr
|
||||
%s willst nen Kaffee ?
|
||||
Meine Augen sind schon ganz klein
|
||||
Man nach 5 Stunden schlafen mir die Fuesse ein...
|
||||
|
||||
@KEY "VOTE", "MAPCHANGE"
|
||||
Nee, ich mag %m
|
||||
Nur weil du immer tot bist %s ?
|
||||
Wieso treff ich auf %m nie was?
|
||||
%m ist geil, halt die Fresse!
|
||||
%m ownz!
|
||||
Ja, wir sollten jetzt mal voten.
|
||||
Och nee lass ma
|
||||
Die Map ist doch cool
|
||||
Verstehe nicht wie man diese Map moegen kann?
|
||||
Ey ich loose immer total ab auf %m
|
||||
|
||||
@KEY "WAS", "WARUM", "WIESO", "WESHALB", "WO", "WER", "WANN", "WIE"
|
||||
Das wirst du nie herausfinden, %s!
|
||||
Ja, das ist schon sehr seltsam, %s...
|
||||
Die Wahrheit ist irgendwo dort draussen, %s ;-)
|
||||
Keine Ahnung, %s
|
||||
Was glaubst du, %s?
|
||||
Ich kanns dir nich sagen, %s!
|
||||
Das musst du schon selber rausfinden, %s!
|
||||
Gute Frage, %s!
|
||||
Ich sags dir nich %s
|
||||
Du kommst nie drauf %s
|
||||
Versuchs gar nicht erst %s
|
||||
Frag Captain Kirk %s
|
||||
Wer soll das wissen %s?
|
||||
|
||||
@KEY "WIEDER"
|
||||
Dinge wiederholen sich immer wieder, stimmts?
|
||||
Und ich bin sicher, es war nicht das letzte Mal...
|
||||
So laeuft die Sache nun mal, hey...
|
||||
Immer dasselbe!
|
||||
Schon wieder?
|
||||
Nee echt ich packs nicht mehr!
|
||||
|
||||
[UNKNOWN]
|
||||
Bla bla bla...
|
||||
Was hast du gesagt %s?
|
||||
Konzentrier dich aufs Spiel, %s!
|
||||
Mit dir zu chatten, %s, ist ja sooo toll!
|
||||
Diese verfluchten chatmessages kotzen mich langsam an!
|
||||
Nicht spammen %s!
|
||||
Wie hast du es nur geschafft so viel Scheisse in so kurzer Zeit zu schreiben?
|
||||
Ja, %s. Du hast recht!
|
||||
Auf keinen Fall, %s...
|
||||
Seid doch mal kurz ruhig
|
||||
Wo kommst du her, %s?
|
||||
Boah die in meinem alten Clan sind echt krank!
|
||||
Bist du sicher, %s?
|
||||
Bin mal auf CS nach Source gespannt
|
||||
Ich sehs, %s!
|
||||
Warum sagen immer alle dasselbe???
|
||||
Ueber was zur Hoelle redest du, %s?
|
||||
Du glaubst gar nicht wie egal mir das alles ist
|
||||
Hey, halts Maul und spiel, %s!
|
||||
Meine alten LAN-Kumpels haben alle schon Kinder! Mensch bin ich alt!
|
||||
Ich glaub ich spiele viel zu viel CS
|
||||
Quake 1 Tenebrae rockt auch total ab man!
|
||||
Ob Valve bald an die Boerse geht? Die muessen doch gut verdienen jetzt.
|
||||
Hast du was gesagt, %s?
|
||||
Denkt Euch mal was neues aus.
|
||||
Wen interessiert das mensch?
|
||||
Wolfenstein! Das war noch ein Shooter!
|
||||
Wer hat das gesagt?
|
||||
Oh, wirklich?
|
||||
Esports finde ich total laecherlich
|
||||
Ich hoffe wir kommen hier mal endlich weiter...
|
||||
Mein neuer Job ist echt gut und der Chef ist nett.
|
||||
Sehr witzig, %s!
|
||||
Mein neuer Job ist so Oede! Naja hauptsache die Kohle kommt rein...
|
||||
Wer will denn in einem Clan sein?
|
||||
Im bin im besten Clan des Landes!
|
||||
Ich hasse diese dummen Kommentare, %s!
|
||||
Weiss irgend jemand hier wie man den Gaussjump macht?
|
||||
ZZZZZZZzzzzzz...
|
||||
Was geht ?
|
||||
Mir is sooo langweilig...
|
||||
Hast du ICQ, %s?
|
||||
Frueher war alles besser!
|
||||
Man Kellerkinder sucht Euch mal ein Leben da draussen
|
||||
Wenn noch einer was gegen Esports sagt gibts Kloppe
|
||||
Junge, junge ist das wieder langsam heute...
|
||||
Duke Nukem forever!
|
||||
Hoer doch mal mit Deinem Progamer-gesuelze auf- interessiert keinen
|
||||
Alter du bist echt abartig !!
|
||||
Heh, wollt ihr zocken oder labern ?
|
||||
Neulich meinte so ein zwoelfjaehriger zu mir er haette Steam gehackt
|
||||
%s das tangiert mich nur peripher - know what I mean?
|
||||
na sicher %s
|
||||
Echt keinen Plan
|
||||
Geht mir voll vorbei...
|
||||
828
cfg/addons/yapb/conf/lang/de_lang.cfg
Normal file
828
cfg/addons/yapb/conf/lang/de_lang.cfg
Normal file
|
|
@ -0,0 +1,828 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: de_lang.cfg
|
||||
;
|
||||
; Configuration file contains German translation for bots menus and messages.
|
||||
;
|
||||
|
||||
[ORIGINAL]
|
||||
\yMain Menu\w
|
||||
|
||||
1. Control Bots
|
||||
2. Features
|
||||
|
||||
3. Fill Server
|
||||
4. End Round
|
||||
|
||||
0. Exit
|
||||
|
||||
|
||||
[TRANSLATED]
|
||||
\yBots Hauptmenue\w
|
||||
|
||||
1. YaPB Bot-Kontrolle
|
||||
2. YaPB-Funktionen
|
||||
|
||||
3. Server mit Bots fuellen
|
||||
4. Runde beenden
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Features\w
|
||||
|
||||
1. Weapon Mode Menu
|
||||
2. Waypoint Menu
|
||||
3. Select Personality
|
||||
|
||||
4. Toggle Debug Mode
|
||||
5. Command Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB-Funktionen\w
|
||||
|
||||
1. Waffenmodus-Menue
|
||||
2. Wegpunkte-Menue
|
||||
3. Bot-Charakter auswaehlen
|
||||
|
||||
4. Fehlererkennungs-Modus
|
||||
5. Befehls-Menue
|
||||
|
||||
0. Ausgang
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yYaPB Control Menu\w
|
||||
|
||||
1. Add a Bot, Quick
|
||||
2. Add a Bot, Specified
|
||||
|
||||
3. Remove Random Bot
|
||||
4. Remove All Bots
|
||||
|
||||
5. Remove Bot Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yYaPB Bot-Optionen\w
|
||||
|
||||
1. Bot schnell hinzufuegen
|
||||
2. Speziellen Bot hinzufuegen
|
||||
|
||||
3. Zufaelligen Bot hinauswerfen
|
||||
4. Alle Bots hinauswerfen
|
||||
|
||||
5. Entferne Bot-Menue
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Weapon Mode\w
|
||||
|
||||
1. Knives only
|
||||
2. Pistols only
|
||||
3. Shotguns only
|
||||
4. Machine Guns only
|
||||
5. Rifles only
|
||||
6. Sniper Weapons only
|
||||
7. All Weapons (Standard)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBot Waffen-Modus\w
|
||||
|
||||
1. Nur Messer
|
||||
2. Nur Pistolen
|
||||
3. Nur Schrotflinten
|
||||
4. Nur Maschinengewehre
|
||||
5. Nur Gewehre
|
||||
6. Nur Scharfschuetzen-Waffen
|
||||
7. Alle Waffen (Standard)
|
||||
|
||||
0. Ausgang
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Personality\w
|
||||
|
||||
1. Random
|
||||
2. Normal
|
||||
3. Aggressive
|
||||
4. Defensive
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBot Persoenlichkeit\w
|
||||
|
||||
1. Zufall
|
||||
2. Normal
|
||||
3. Aggressiv
|
||||
4. Defensiv
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Difficulty Level\w
|
||||
|
||||
1. Newbie
|
||||
2. Average
|
||||
3. Normal
|
||||
4. Professional
|
||||
5. Godlike
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBot Schwierigkeit\w
|
||||
|
||||
1. Dumm (0-20)
|
||||
2. Neuling (20-40)
|
||||
3. Gewoehnlich (40-60)
|
||||
4. Geuebt (60-80)
|
||||
5. Professionell (80-99)
|
||||
6. Wie ein Gott (100)
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect a team\w
|
||||
|
||||
1. Terrorist Force
|
||||
2. Counter-Terrorist Force
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yTeam auswaehlen\w
|
||||
|
||||
1. Terroristen
|
||||
2. Anti-Terroreinheit
|
||||
|
||||
5. Automatisch
|
||||
|
||||
0. Ausgang
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yModell auswaehlen\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. Automatisch
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yModell auswaehlen\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. Automatisch
|
||||
|
||||
0. Ausgang
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 1)\w
|
||||
|
||||
1. Show/Hide waypoints
|
||||
2. Cache waypoint
|
||||
3. Create path
|
||||
4. Delete path
|
||||
5. Add waypoint
|
||||
6. Delete waypoint
|
||||
7. Set Autopath Distance
|
||||
8. Set Radius
|
||||
|
||||
9. Next...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yWegpunkte Menue (Seite 1)\w
|
||||
|
||||
1. Wegpunkte sichtbar/unsichtbar
|
||||
2. Pfad Beginn
|
||||
3. Pfad Ende
|
||||
4. loesche Pfad Beginn
|
||||
5. loesche Pfad Ende
|
||||
6. Wegpunkt hinzufuegen
|
||||
7. Wegpunkt loeschen
|
||||
8. Radius setzen
|
||||
|
||||
9. Naechstes...
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 2)\w
|
||||
|
||||
1. Waypoint stats
|
||||
2. Autowaypoint on/off
|
||||
3. Set flags
|
||||
4. Save waypoints
|
||||
5. Save without checking
|
||||
6. Load waypoints
|
||||
7. Check waypoints
|
||||
8. Noclip cheat on/off
|
||||
|
||||
9. Previous...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yWegpunkte Menue (Seite 2)\w
|
||||
|
||||
1. Wegpunkte Statistik
|
||||
2. Auto-Wegpunkte an/aus
|
||||
3. Fahnen setzen
|
||||
4. Wegpunkte speichern
|
||||
5. Wegpunkte speichern ohne Test
|
||||
6. Wegpunkte Laden
|
||||
7. Wegpunkte testen
|
||||
8. Noclip Cheat an/aus
|
||||
|
||||
9. Vorheriges...
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Radius\w
|
||||
|
||||
1. 0
|
||||
2. 8
|
||||
3. 16
|
||||
4. 32
|
||||
5. 48
|
||||
6. 64
|
||||
7. 80
|
||||
8. 96
|
||||
9. 128
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yWegpunkte Radius\w
|
||||
|
||||
1. 0
|
||||
2. 8
|
||||
3. 16
|
||||
4. 32
|
||||
5. 48
|
||||
6. 64
|
||||
7. 80
|
||||
8. 96
|
||||
9. 128
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Type\w
|
||||
|
||||
1. Normal
|
||||
\r2. Terrorist Important
|
||||
3. Counter-Terrorist Important
|
||||
\w4. Block with hostage
|
||||
\y5. Rescue Zone
|
||||
\w6. Camping
|
||||
7. Camp End
|
||||
\r8. Map Goal
|
||||
\w9. Jump
|
||||
|
||||
\w0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yWegpunkt Typ\w
|
||||
|
||||
1. Normal
|
||||
\r2. Wichtig fuer Terroristen
|
||||
3. Wichtig fuer Anti Terroreinheiten
|
||||
\w4. Fuer Geiseln kein Durchgang
|
||||
\y5. Rettungszone
|
||||
\w6. Camping
|
||||
7. Camping Ende
|
||||
\r8. Ziel (Bombe/Geiseln)
|
||||
\w9. Sprung
|
||||
|
||||
\w0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Flags\w
|
||||
|
||||
\yAdd waypoint flag:\w
|
||||
|
||||
1. Block with Hostage
|
||||
2. Terrorists Specific
|
||||
3. CTs Specific
|
||||
4. Use Elevator
|
||||
|
||||
\yDelete waypoint flag:\w
|
||||
|
||||
5. Block with Hostage
|
||||
6. Terrorists Specific
|
||||
7. CTs Specific
|
||||
8. Use Elevator
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yWegpunktfahnen:\w
|
||||
|
||||
\yWegpunktfahne hinzufuegen:\w
|
||||
|
||||
1. Fuer Geiseln kein Durchgang
|
||||
2. Wichtig fuer Terroristen
|
||||
3. Wichtig fuer Anti Terroreinheiten
|
||||
4. Aufzug benutzen
|
||||
|
||||
\yWegpunktfahne loeschen:\w
|
||||
|
||||
5. Fuer Geiseln kein Durchgang
|
||||
6. Wichtig fuer Terroristen
|
||||
7. Wichtig fuer Anti-Terroreinheiten
|
||||
8. Aufzug benutzen
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yBot Command Menu\w
|
||||
|
||||
1. Make Double Jump
|
||||
2. Finish Double Jump
|
||||
|
||||
3. Drop the C4 Bomb
|
||||
4. Drop the Weapon
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yBot Befehls-Menue\w
|
||||
|
||||
1. Doppel-Sprung erstellen
|
||||
2. Doppel-Sprung beenden
|
||||
|
||||
3. C4-Bombe fallenlassen
|
||||
4. Waffe fallenlassen
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yAutoPath Distance\w
|
||||
|
||||
1. Distance 0
|
||||
2. Distance 100
|
||||
3. Distance 130
|
||||
4. Distance 160
|
||||
5. Distance 190
|
||||
6. Distance 220
|
||||
7. Distance 250 (Default)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yAuto-Pfad Entfernung\w
|
||||
|
||||
1. Entfernung 0
|
||||
2. Entfernung 100
|
||||
3. Entfernung 130
|
||||
4. Entfernung 160
|
||||
5. Entfernung 190
|
||||
6. Entfernung 220
|
||||
7. Entfernung 250 (Standard)
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
\yCreate Path (Choose Direction)\w
|
||||
|
||||
1. Outgoing Path
|
||||
2. Incoming Path
|
||||
3. Bidirectional (Bot Ways)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yPfad erstellen (Waehle Richtung)\w
|
||||
|
||||
1. Ausgehender Pfad
|
||||
2. Eingehender Pfad
|
||||
3. Pfad in beide Richtungen
|
||||
|
||||
0. Ausgang
|
||||
|
||||
[ORIGINAL]
|
||||
Map not waypointed. Can't Create Bot
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte nicht vorhanden. Kann Bot nicht hinzufuegen.
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints has been changed. Load waypoints again...
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte wurden geaendert. Lade Wegpunkte neu...
|
||||
|
||||
[ORIGINAL]
|
||||
Invalid skill given. Using random skill.
|
||||
|
||||
[TRANSLATED]
|
||||
Ungueltiges Koennen vergeben. Zufaelliges Koennen gewaehlt.
|
||||
|
||||
[ORIGINAL]
|
||||
Connecting Bot...
|
||||
|
||||
[TRANSLATED]
|
||||
Verbinden Bot...
|
||||
|
||||
[ORIGINAL]
|
||||
Fill Server with %s bots...
|
||||
|
||||
[TRANSLATED]
|
||||
Server mit %s Bots auffuellen...
|
||||
|
||||
[ORIGINAL]
|
||||
Bots are removed from server.
|
||||
|
||||
[TRANSLATED]
|
||||
Bots sind vom Server entfernt.
|
||||
|
||||
[ORIGINAL]
|
||||
Bot '%s' kicked
|
||||
|
||||
[TRANSLATED]
|
||||
Bot '%s' beseitigt
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Remove Menu (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. Back
|
||||
|
||||
[TRANSLATED]
|
||||
\yBots Entfernen-Menue (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. Zurueck
|
||||
|
||||
[ORIGINAL]
|
||||
%s\d %1.1d. Not a Bot\w
|
||||
|
||||
[TRANSLATED]
|
||||
%s\d %1.1d. Kein Bot\w
|
||||
|
||||
[ORIGINAL]
|
||||
9. More...
|
||||
|
||||
|
||||
[TRANSLATED]
|
||||
9. Mehr...
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
All Bots died !
|
||||
|
||||
[TRANSLATED]
|
||||
Alle Bots sind tot.
|
||||
|
||||
[ORIGINAL]
|
||||
%s weapon mode selected
|
||||
|
||||
[TRANSLATED]
|
||||
%s Waffenmodus ausgewaehlt
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Source Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
Error: Pfadfindungs-Anfang ungueltig->%d
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Destination Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
Error: Pfadfindungsrichtung ungueltig->%d
|
||||
|
||||
[ORIGINAL]
|
||||
Denied path creation from %d to %d (path already exists)
|
||||
|
||||
[TRANSLATED]
|
||||
Keine Pfad-Erstellung von %d nach %d (Pfad besteht schon)
|
||||
|
||||
[ORIGINAL]
|
||||
Path added from %d to %d
|
||||
|
||||
[TRANSLATED]
|
||||
Pfad erstellt von %d zu %d
|
||||
|
||||
[ORIGINAL]
|
||||
This is not Camping Waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Das ist kein Camping-Wegpunkt
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint number out of range (Valid range From 0 to %d)
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt Nr. ausser Reichweite (Zulaessige Reichweite von 0 bis %d)
|
||||
|
||||
[ORIGINAL]
|
||||
Cannot connect waypoint to itself
|
||||
|
||||
[TRANSLATED]
|
||||
Kann Wegpunkt nicht mit sich selbst verbinden!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d connected with invalid Waypoint Nr. %d!
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt %d verbunden mit dem ungueltigen Wegpunkt Nr. %d!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d isn't connected with any other Waypoint!
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt %d ist mit keinem Wegpunkt verbunden!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d pathnumber differs from index!
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt %d -Pfadnummer ist verschieden vom Index!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d Camp-Endposition not set!
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt %d Camping-Ende Position nicht gesetzt!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set a Rescue Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Kein Geiselrettungs-Wegpunkt gesetzt!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Terrorist Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Kein Terroristen-wichtiger Wegpunkt gesetzt!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any CT Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Kein CT-wichtiger Wegpunkt gesetzt!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Goal Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Kein Ziel-Wegpunkt gesetzt!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint Nr. 0 to Waypoint Nr. %d!
|
||||
|
||||
[TRANSLATED]
|
||||
Pfad unterbrochen von Wegpunkt Nr. 0 zu Nr. %d!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint Nr. %d to Waypoint Nr. 0!
|
||||
|
||||
[TRANSLATED]
|
||||
Pfad unterbrochen von Wegpunkt Nr. %d zu Nr. 0!
|
||||
|
||||
[ORIGINAL]
|
||||
Choose weapon from 1 to 7 range
|
||||
|
||||
[TRANSLATED]
|
||||
Waehle Waffe von 1 bis 7
|
||||
|
||||
[ORIGINAL]
|
||||
All dead bots will vote for map #%d
|
||||
|
||||
[TRANSLATED]
|
||||
Alle toten Bots stimmen fuer Map #%d
|
||||
|
||||
[ORIGINAL]
|
||||
Bot %s executing command %s
|
||||
|
||||
[TRANSLATED]
|
||||
Bot %s fuehrt Befehl %s aus
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint cleared
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte zurueckgesetzt
|
||||
|
||||
[ORIGINAL]
|
||||
Player is NOT Bot!
|
||||
|
||||
[TRANSLATED]
|
||||
Spieler ist kein Bot!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte-Bearbeitung ist an
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte-Bearbeitung ist aus
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Noclip-cheat ist AN
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte sind AUS
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte sind AN
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Noclip-cheat ist AUS
|
||||
|
||||
[ORIGINAL]
|
||||
Showing Direction to Waypoint #%d
|
||||
|
||||
[TRANSLATED]
|
||||
Zeige Richtung zum Wegpunkt #%d
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints saved
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte gespeichert
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints loaded
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte geladen
|
||||
|
||||
[ORIGINAL]
|
||||
Nodes work Fine
|
||||
|
||||
[TRANSLATED]
|
||||
Alle Wegpunkte funktionieren!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Nr. %d now cached
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt Nr. %d zwischengespeichert
|
||||
|
||||
[ORIGINAL]
|
||||
Player '%s' teleported to waypoint #%d (x:%d, y:%d, z:%d)
|
||||
|
||||
[TRANSLATED]
|
||||
Spieler '%s' wurde zu Wegpunkt #%d (x:%d, y:%d, z:%d) teleportiert
|
||||
|
||||
[ORIGINAL]
|
||||
Experience tab saved
|
||||
|
||||
[TRANSLATED]
|
||||
Erfahrungs-Datei gespeichert
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Erfahrung sammeln AN
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Erfahrung sammeln AUS
|
||||
|
||||
[ORIGINAL]
|
||||
Command not supported on dedicated server
|
||||
|
||||
[TRANSLATED]
|
||||
Befehl nicht moeglich auf dediziertem Server
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint not saved
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkte nicht gespeichert!
|
||||
|
||||
[ORIGINAL]
|
||||
There are errors, see console
|
||||
|
||||
[TRANSLATED]
|
||||
Es gibt Fehler, Konsole beachten!
|
||||
|
||||
[ORIGINAL]
|
||||
You're dead, and have no access to this menu
|
||||
|
||||
[TRANSLATED]
|
||||
Du bist tot und hast keinen Zugriff zu diesem Menue
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath disabled
|
||||
|
||||
[TRANSLATED]
|
||||
AutoPfad aus
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath maximum distance set to %f
|
||||
|
||||
[TRANSLATED]
|
||||
AutoPfad maximale Distanz gesetzt auf %f
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find nearest waypoint in 50 units
|
||||
|
||||
[TRANSLATED]
|
||||
Kann den naechste? Wegpunkt nicht innerhalb von 50 Einheiten finden
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find destination waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Kann Zielwegpunkt nicht finden
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to connect waypoint with itself
|
||||
|
||||
[TRANSLATED]
|
||||
Kann Wegpunkt nicht mit sich selbst verbinden
|
||||
|
||||
[ORIGINAL]
|
||||
There is already no path on this waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Es gibt keinen Pfad zu diesem Wegpunkt
|
||||
|
||||
[ORIGINAL]
|
||||
Cached waypoint cleared (nearby point not found in 50 units range)
|
||||
|
||||
[TRANSLATED]
|
||||
Temorärer Wegpunkt geloescht (kein Punkt gefunden innerhalb 50 Einheiten Entfernung)
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint #%d has been put into memory
|
||||
|
||||
[TRANSLATED]
|
||||
Wegpunkt #%d wurde in den Speicher geladen.
|
||||
|
||||
[ORIGINAL]
|
||||
Maximum players reached (%d/%d). Unable to create Bot.
|
||||
|
||||
[TRANSLATED]
|
||||
Maximale Spieleranzahl erreicht (%d/%d). Kann Bot nicht einfuegen.
|
||||
371
cfg/addons/yapb/conf/lang/en_chat.cfg
Normal file
371
cfg/addons/yapb/conf/lang/en_chat.cfg
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: en_chat.cfg
|
||||
;
|
||||
; Configuration file contains English translation for bot chats.
|
||||
;
|
||||
|
||||
[BOMBPLANT]
|
||||
Jeeesuzzz Christ, not again!
|
||||
Come on %t, let's search the bomb!
|
||||
Last time it took me 5 secs to find & defuse it...
|
||||
Say, is it the red or the blue wire?
|
||||
...And my Heart goes boooom *grin*
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Messages after killing somebody:
|
||||
// Minimum Number is 1
|
||||
// For the %v the name of the victim will
|
||||
// be inserted
|
||||
// NOTE: Include a %v placeholder in every Line!
|
||||
//
|
||||
[KILLED]
|
||||
%v, you're no match for me!
|
||||
Sorry, %v. You got in my way.
|
||||
You flew back pretty good, %v.
|
||||
I had to do it, %v. You understand.
|
||||
You should've run while you had the chance, %v.
|
||||
I've always been better, %v. Always.
|
||||
I bet you hate it when that happens, don't you, %v?
|
||||
That'll teach you, %v!
|
||||
Hey, come on, %v! You almost hurt me this time.
|
||||
Ha...ha!
|
||||
You are nothing, %v. Nothing at all.
|
||||
%v I worry about you...
|
||||
Sorry %v, my Headshot Script is better than yours.
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Chat Messages when bot connects to server
|
||||
// !!Minimum Number is 1!!
|
||||
[WELCOME]
|
||||
Hi guys :)
|
||||
Wazzzzup?
|
||||
My god, i see there are many cheaters on this server...
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// Chat Messages when dead and bored
|
||||
// !!Minimum Number is 9!!
|
||||
//
|
||||
[DEADCHAT]
|
||||
It makes me sick to look at those Fools
|
||||
It's time for a mapchange, isn't it?
|
||||
%t GO,GO,GO!!
|
||||
I'm so booored!
|
||||
I can't believe %f isn't cheating
|
||||
Spectating sucks...
|
||||
I wish someone good would join the server.
|
||||
That looked painful.
|
||||
This is quite fun.
|
||||
%r in the round and I'm already spectating :(
|
||||
Why does everyone keep trying to hurt me :)
|
||||
Visit http://podbot.nuclearbox.com
|
||||
My handwrist already hurts...
|
||||
This Map sucks hard...
|
||||
I'm having a bad day
|
||||
%r and %t is still alive! Something must be wrong...
|
||||
Will they stop camping now? Only %r left!!
|
||||
I'm better at Quake 3, that's for sure!
|
||||
Still %r in this round
|
||||
Botman must be such a cool guy...
|
||||
Stupid Bots!
|
||||
Look at those idiots!
|
||||
I bet %t won't make it through the round
|
||||
I'm so tired today...
|
||||
I really should go to bed now.
|
||||
I usually don't play that bad!
|
||||
No %m today, please!
|
||||
I really hate %m :(
|
||||
Sniping is all they can do.
|
||||
LOL! Look at %t!
|
||||
Please vote for a mapchange!!!
|
||||
Did one of the bots get stuck already?
|
||||
Boooooom!!! *lol*
|
||||
Insane in the membrane, hehe!
|
||||
I'm sure that Guy used an Aimbot!
|
||||
HEY %f YOU DAMN CHEATER!
|
||||
Are there Bots in this Game?
|
||||
Would you give me your Headshot Script?
|
||||
Next Round we should stick together.
|
||||
Fuck all those Teamkillers!!!
|
||||
Woah %f has nice stats!!
|
||||
What are Clans all about? I don't get it
|
||||
Do you know Jumbot? It really kicks Ass!
|
||||
If botman is cool, what is TheFatal then?
|
||||
Fucking lagged!!
|
||||
IMHO NNBot is much better than RealBot.
|
||||
Too bad Android Bot is updated so slowly.
|
||||
I'm off for a cigarette break...
|
||||
Why did they include the vehicles in CS?
|
||||
I had to reload and he shot me in the head!
|
||||
|
||||
// Start of the "dynamic" replies from here
|
||||
// After each @KEY Tag you need to specify the
|
||||
// keywords in quotation marks and uppercase. You can
|
||||
// have several keywords (aliases) each separated by a comma.
|
||||
// After the keywords line, the answers or messages to this
|
||||
// special keyword need to be given. In theory there can be an unlimited
|
||||
// number of answers of course you should care about the used memory ;)
|
||||
|
||||
[REPLIES]
|
||||
|
||||
@KEY " AGAIN "
|
||||
%s, things are always repeating - aren't they?
|
||||
And I'm sure it wasn't the last time...
|
||||
That's the way things go, hey...
|
||||
|
||||
@KEY "AIMBOT", "WALLHACK"
|
||||
%s, are you cheating?
|
||||
Even PunkBuster fails to detect some of them...
|
||||
You can't be sure nowadays if someones's good at playing or cheats
|
||||
Aimbots are cool, shut up %s!
|
||||
Wallhacks are evil tools of the devil ;)
|
||||
|
||||
@KEY " ALWAYS "
|
||||
That's not always, %s!
|
||||
I just like it :-)
|
||||
Come on %s, that was only the second time!
|
||||
|
||||
@KEY "ANDROID"
|
||||
Ah yes, those were the times...
|
||||
%s was it your first Bot too?
|
||||
Does anybody know what DaTa does today?
|
||||
You can't play with Android on %m, can you?
|
||||
|
||||
@KEY "BOTMAN"
|
||||
Who is this botman everybody is talking about???
|
||||
Visit his website at http://www.planethalflife.com/botman
|
||||
Without his sourcecode many bots wouldn't exist!
|
||||
I wonder when HPB-Bot will be finished...
|
||||
Did you play his HPB-Bot yet?
|
||||
|
||||
@KEY " BOT ", "BOTS"
|
||||
Why are you always talking about them?
|
||||
There are no bots on this server %s, I tell you!
|
||||
Bots are cool!!!
|
||||
What's your favorite bot, %s?
|
||||
If you want to program your own, ask botman!
|
||||
Bots, all the time bots - you should start playing with humans.
|
||||
Most bots are still very stupid!
|
||||
|
||||
@KEY "CAMPER", "CAMPING"
|
||||
I really hate those campers!
|
||||
Camping sucks!
|
||||
Don't you camp sometimes %s?
|
||||
Camping's often the only option to win...
|
||||
Yes, good 'ole Camper-Strike...
|
||||
|
||||
@KEY "CHEAT"
|
||||
Those damn cheaters are ruining the entire game!
|
||||
I suspect that %f is cheating
|
||||
I hate cheaters!
|
||||
Cheating sucks!
|
||||
Why are so many people cheating?
|
||||
Punkbuster could help...
|
||||
Play with bots - they don't cheat!
|
||||
|
||||
@KEY " CLAN "
|
||||
What are these clans all about?
|
||||
I was in a clan once, but it sucked hard.
|
||||
What clan are you from, %s?
|
||||
Do you want to enter our clan, %s?
|
||||
Playing in a clan is for people who got no life...
|
||||
|
||||
@KEY " CS ", "COUNTERSTRIKE", "COUNTER-STRIKE", "CSTRIKE"
|
||||
Counter-Strike is boring nowadays...
|
||||
%s how long do you play CS?
|
||||
CS all the way from the very first beta!
|
||||
There are too much newbies playing it.
|
||||
Too many people online cheat in CS
|
||||
It's not as much fun as it used to be
|
||||
|
||||
@KEY " DOD ", "DAY OF DEFEAT"
|
||||
I don't get what people like in DoD
|
||||
CS all the way...
|
||||
%s do you think it will get as popular as CS?
|
||||
%s do you prefer DoD over CS?
|
||||
Day of Defeat is a hopeless MOD, IMHO.
|
||||
|
||||
@KEY " ENGINE "
|
||||
I heard the HL Engine is a hybrid between Quake1 & Quake2, odd huh?
|
||||
%s, don't you miss the time when an engine was a Software Engine?
|
||||
The HL Engine is still quite good, despite its age...
|
||||
Code your own engine %s!
|
||||
|
||||
@KEY "FUCK", "DAMN", "PISS"
|
||||
Don't swear, %s!
|
||||
Nasty %s!
|
||||
Yes, you're right, %s. Now SHUT UP!
|
||||
Watch your language, %s!
|
||||
%s, don't use this word again - that's impolite!
|
||||
|
||||
@KEY "HEHE", "HAHA", "LOL", ":)"
|
||||
I'm glad that at least you have your fun, %s...
|
||||
Enjoy yourself while you still can, %s!
|
||||
Very funny indeed, %s...
|
||||
Good one %s!
|
||||
|
||||
@KEY "I THINK ", "I BELIEVE "
|
||||
You think too much, %s ;-)
|
||||
And I think you should shut up and play!
|
||||
And you really do believe that, %s?
|
||||
What makes you think so?
|
||||
Plz give me your ICQ Number %s
|
||||
|
||||
@KEY "JOEBOT"
|
||||
Yes, JoeBot isn't bad...
|
||||
Funnily JoeBot got famous when NNBot quit...
|
||||
I wonder where else Neural Networks could be applied
|
||||
So you think JoeBot rocks?
|
||||
|
||||
@KEY "JUMBOT"
|
||||
JB? It was good back then but ParaBot is much better now!
|
||||
JB's advantage has been that it was a MOD, not a hooking DLL
|
||||
Ah yes, Jumbot and The Fatal. Wonder what he's up to now.
|
||||
Rumours have it that The Fatal now does AHL Bots?
|
||||
|
||||
@KEY " MUSIC ", " BAND "
|
||||
Umm...I don't care as long as it's no commercial shit
|
||||
Underground Electro Polka is the real deal!
|
||||
Do you still use Napster %s?
|
||||
Somebody got good MP3 Links?
|
||||
|
||||
@KEY "NNBOT"
|
||||
Too bad NNBot is discontinued...
|
||||
Try JoeBot if you liked NNBot %s
|
||||
%s did you hear of Ditlew's new MOD?
|
||||
|
||||
@KEY "PARABOT"
|
||||
ParaBot is a the coolest Deathmatch Bot I've ever played
|
||||
%s you should try ParaBot, it's great!
|
||||
It's so sad no CSBot has the great Nav of Parabot so far
|
||||
I heard it already supports 3 HL MODS by now
|
||||
|
||||
@KEY " PING ", "LAGG"
|
||||
I always have a Ping of 5, I'm on DSL!!
|
||||
My connection sucks...
|
||||
Where are you from %s?
|
||||
Play offline with Bots if your connection sucks
|
||||
Just change your provider %s!
|
||||
|
||||
@KEY "POD-BOT", " POD ", "PODBOT"
|
||||
I heard it's the best bot for CS, I'm not sure though...
|
||||
Yeah, it rulez!
|
||||
People tell they use some kind of wallhack, is it true?
|
||||
|
||||
@KEY "PUNKBUSTER"
|
||||
Don't be a PUNK! (support www.punkbuster.com)
|
||||
I'm always lagging when using PunkBuster
|
||||
Tony Ray of PB is kind of weird...
|
||||
|
||||
@KEY "Q3", "QUAKE"
|
||||
Q3 has a bad lighting IMO
|
||||
Half-Life still rules %s!
|
||||
Have you heard of DMC, %s? ;-)
|
||||
|
||||
@KEY "REALBOT"
|
||||
Is it any good %s?
|
||||
Is RB still unwaypointed %s?
|
||||
Yep, I remember RB. First unwaypointed Bot right?
|
||||
I heard RB now tries to do something like ParaBot?!?
|
||||
Once lovingly called 'the wallhuggers'
|
||||
|
||||
@KEY "SCRIPT"
|
||||
Scripts are for losers
|
||||
%s, you prolly don't know how to bind keys?
|
||||
Did you know that even buying scripts are considered cheating?
|
||||
|
||||
@KEY "SERVER"
|
||||
I'm always on this Server
|
||||
Me & my friends play a lot on this Server
|
||||
I believe this Server's got a good Map Rotation
|
||||
|
||||
@KEY "SORRY"
|
||||
Yeah, afterwards everybody says he's sorry!
|
||||
The excuse doesn't help me now, %s!
|
||||
Next time you better think before you start doing something, %s!
|
||||
I'm sorry, too!
|
||||
You don't know how sorry you will be for doing that...
|
||||
|
||||
@KEY "TEAMKILL", " TK "
|
||||
Teamkillers should be banned from this server.
|
||||
Who's the teamkiller %s?
|
||||
I like stabbing my teammates, MWUHAHA!!
|
||||
Did %t kill you? He often does!
|
||||
Where's the Admin? He should take care of it...
|
||||
%s just sit out %r and pay him back!
|
||||
|
||||
@KEY "TIRED", "SLEEP"
|
||||
Go to bed, %s
|
||||
Have some rest, %s...
|
||||
Want some coffee %s?
|
||||
Oh come on %s! One more round...
|
||||
|
||||
@KEY "VOTE", "MAPCHANGE"
|
||||
Nah, I like %m
|
||||
Just because you're always dead %s?
|
||||
%m is great, shut up!
|
||||
%m ownz!
|
||||
Yep. We should vote now.
|
||||
|
||||
@KEY "WHAT ", "WHY ", "WHERE ", "WHO ", "WHEN ", "HOW "
|
||||
You will never find out, %s!
|
||||
Yeah, that's really strange %s...
|
||||
The answer is out there, %s ;-)
|
||||
No idea, %s
|
||||
Dunno.
|
||||
What do you think %s?
|
||||
I won't tell you, %s!
|
||||
Find out yourself, %s!
|
||||
Good question, %s!
|
||||
|
||||
[UNKNOWN]
|
||||
Bla bla bla...
|
||||
What did you say, %s?
|
||||
Concentrate on the game, %s!
|
||||
Chatting with you %s is so great!
|
||||
These damn chat-messages are freaking me out!
|
||||
Don't spam, %s!
|
||||
How do you find the time to type all this crap???
|
||||
Yeah, %s. You're right!
|
||||
No way, %s...
|
||||
Where are you from, %s?
|
||||
I can't believe how you can play and type at the same time, %s!
|
||||
Are you sure, %s?
|
||||
I see, %s!
|
||||
Why is everybody always saying the same things???
|
||||
What the heck are you talkin' about, %s?
|
||||
Hey, shut up and play, %s!
|
||||
You said somethin', %s?
|
||||
Who said that?
|
||||
Oh, really?
|
||||
Very funny, %s!
|
||||
I'm in the best clan of my country!
|
||||
I hate these stupid comments, %s!
|
||||
Does anybody know how to do the Gauss-jump?
|
||||
ZZZZZZZzzzzzz
|
||||
Wazzzzuuuuuuup?
|
||||
I'm so booooored...
|
||||
Have you got ICQ, %s?
|
||||
It's damn slow today...
|
||||
OMG you're weird!
|
||||
Do you want to play or chat all the time?
|
||||
I don't really want to know %s
|
||||
Certainly.
|
||||
Huh? WTF?
|
||||
57
cfg/addons/yapb/conf/lang/en_names.cfg
Normal file
57
cfg/addons/yapb/conf/lang/en_names.cfg
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: en_names.cfg
|
||||
;
|
||||
; Configuration file contains English bot names.
|
||||
;
|
||||
|
||||
Fragnatic
|
||||
DaTa
|
||||
Botman
|
||||
V0id
|
||||
Android
|
||||
M0rbid Desire
|
||||
Ping of Death
|
||||
Killing Frenzy
|
||||
Campers Death
|
||||
Count Floyd
|
||||
Polymorph
|
||||
Headshot Deluxe
|
||||
Trust Noone
|
||||
Borg Queen
|
||||
Make me Laugh
|
||||
Psyke
|
||||
Eliza
|
||||
Die Humans
|
||||
Alloc
|
||||
killaruna
|
||||
Electrica
|
||||
Ivan
|
||||
Laserdance
|
||||
S.E.S.
|
||||
L33t B0t
|
||||
U're Dead
|
||||
Violently Happy
|
||||
Make my Day
|
||||
Fuzzy Logic
|
||||
Pissed Off
|
||||
Neuromancer
|
||||
Neural Noise
|
||||
//
|
||||
// 32 Names
|
||||
//
|
||||
Dr. No
|
||||
Kugelfang
|
||||
Murder Inc.
|
||||
Bloodlust
|
||||
Pseudolukian
|
||||
Zap!
|
||||
Rambotnic
|
||||
Hemp Invader
|
||||
Dredd
|
||||
Botsie Collins
|
||||
BotsBlitz
|
||||
Funky Byte
|
||||
Berzerk Bot
|
||||
2118
cfg/addons/yapb/conf/lang/ru_chat.cfg
Normal file
2118
cfg/addons/yapb/conf/lang/ru_chat.cfg
Normal file
File diff suppressed because it is too large
Load diff
819
cfg/addons/yapb/conf/lang/ru_lang.cfg
Normal file
819
cfg/addons/yapb/conf/lang/ru_lang.cfg
Normal file
|
|
@ -0,0 +1,819 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: ru_lang.cfg
|
||||
;
|
||||
; Configuration file contains Russian translation for bots menus and messages.
|
||||
;
|
||||
|
||||
[ORIGINAL]
|
||||
\yMain Menu\w
|
||||
|
||||
1. Control Bots
|
||||
2. Features
|
||||
|
||||
3. Fill Server
|
||||
4. End Round
|
||||
|
||||
0. Exit
|
||||
|
||||
|
||||
[TRANSLATED]
|
||||
\yГлавное Меню Бота\w
|
||||
|
||||
1. Контроль Бота
|
||||
2. Навороты
|
||||
|
||||
3. Заполнить Сервер
|
||||
4. Закончить Раунд
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Features\w
|
||||
|
||||
1. Weapon Mode Menu
|
||||
2. Waypoint Menu
|
||||
3. Select Personality
|
||||
|
||||
4. Toggle Debug Mode
|
||||
5. Command Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yНавороты Бота\w
|
||||
|
||||
1. Меню Выбора Режима Оружия
|
||||
2. Меню Вэйпоинтов
|
||||
3. Выбрать Личность Бота
|
||||
|
||||
4. Переключить режим отладки
|
||||
5. Меню Команд Бота
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Control Menu\w
|
||||
|
||||
1. Add a Bot, Quick
|
||||
2. Add a Bot, Specified
|
||||
|
||||
3. Remove Random Bot
|
||||
4. Remove All Bots
|
||||
|
||||
5. Remove Bot Menu
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yМеню контроля Ботов\w
|
||||
|
||||
1. Добавить Бота, Быстро
|
||||
2. Добавить Бота, Настроить
|
||||
|
||||
3. Убрать случайного Бота
|
||||
4. Убрать всех Ботов
|
||||
|
||||
5. Меню убирания Ботов
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Weapon Mode\w
|
||||
|
||||
1. Knives only
|
||||
2. Pistols only
|
||||
3. Shotguns only
|
||||
4. Machine Guns only
|
||||
5. Rifles only
|
||||
6. Sniper Weapons only
|
||||
7. All Weapons
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбрать режим Оружия\w
|
||||
|
||||
1. Только Ножи
|
||||
2. Только Пистолеты
|
||||
3. Только Шотганы
|
||||
4. Только Пулемёты
|
||||
5. Только Винтовки
|
||||
6. Только Снайперки
|
||||
7. Всё оружие
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Personality\w
|
||||
|
||||
1. Random
|
||||
2. Normal
|
||||
3. Aggressive
|
||||
4. Careful
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбор Личности Бота\w
|
||||
|
||||
1. Случайная
|
||||
2. Нормальная
|
||||
3. Агрессивная
|
||||
4. Бот Пасун
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Difficulty Level\w
|
||||
|
||||
1. Newbie
|
||||
2. Average
|
||||
3. Normal
|
||||
4. Professional
|
||||
5. Godlike
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбор скилла Бота\w
|
||||
|
||||
1. Новичок
|
||||
2. Обычный
|
||||
3. Средний
|
||||
4. Профессионал
|
||||
5. БОГ
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect a team\w
|
||||
|
||||
1. Terrorist Force
|
||||
2. Counter-Terrorist Force
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбор команды\w
|
||||
|
||||
1. Террористы
|
||||
2. Менты
|
||||
|
||||
5. Случайно
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбор модели\w
|
||||
1. Phoenix Connexion
|
||||
2. L337 Krew
|
||||
3. Arctic Avengers
|
||||
4. Guerilla Warfare
|
||||
|
||||
5. Случайно
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\ySelect an appearance\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. Auto-select
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yВыбор модели\w
|
||||
|
||||
1. Seal Team 6 (DEVGRU)
|
||||
2. German GSG-9
|
||||
3. UK SAS
|
||||
4. French GIGN
|
||||
|
||||
5. Случайно
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 1)\w
|
||||
|
||||
1. Show/Hide waypoints
|
||||
2. Cache waypoint
|
||||
3. Create path
|
||||
4. Delete path
|
||||
5. Add waypoint
|
||||
6. Delete waypoint
|
||||
7. Set Autopath Distance
|
||||
8. Set Radius
|
||||
|
||||
9. Next...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yОперации с Вэйпонтами (Стр. 1)\w
|
||||
|
||||
1. Пок./Убр. Вэйпоинты
|
||||
2. Запомнить вэйпоинт
|
||||
3. Создать Путь
|
||||
4. Убрать Путь
|
||||
5. Добавить Вэйпоинт
|
||||
6. Удалить Вэйпоинт
|
||||
7. Установить автодистанцию
|
||||
8. Установить радиус
|
||||
|
||||
9. Далее...
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Operations (Page 2)\w
|
||||
|
||||
1. Waypoint stats
|
||||
2. Autowaypoint on/off
|
||||
3. Set flags
|
||||
4. Save waypoints
|
||||
5. Save without checking
|
||||
6. Load waypoints
|
||||
7. Check waypoints
|
||||
8. Noclip cheat on/off
|
||||
|
||||
9. Previous...
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yОперации с Вэйпонтами (Стр. 2)\w
|
||||
|
||||
1. Показать Статистику
|
||||
2. Вкл./Выкл. Автовэйпоинт
|
||||
3. Установить Сигнал
|
||||
4. Сохранить на Диске
|
||||
5. Сохранить без Проверки
|
||||
6. Загрузить Вэйпоинты
|
||||
7. Проверить Вэйпоинты
|
||||
8. Вкл./Выкл. Режим полета
|
||||
|
||||
9. Назад...
|
||||
|
||||
0. Выход
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Radius\w
|
||||
|
||||
1. SetRadius 0
|
||||
2. SetRadius 8
|
||||
3. SetRadius 16
|
||||
4. SetRadius 32
|
||||
5. SetRadius 48
|
||||
6. SetRadius 64
|
||||
7. SetRadius 80
|
||||
8. SetRadius 96
|
||||
9. SetRadius 128
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yУстановка Радиуса\w
|
||||
|
||||
1. Установить 0
|
||||
2. Установить 8
|
||||
3. Установить 16
|
||||
4. Установить 32
|
||||
5. Установить 48
|
||||
6. Установить 64
|
||||
7. Установить 80
|
||||
8. Установить 96
|
||||
9. Установить 128
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yWaypoint Type\w
|
||||
|
||||
1. Normal
|
||||
\r2. Terrorist Important
|
||||
3. Counter-Terrorist Important
|
||||
\w4. Block with hostage / Ladder
|
||||
\y5. Rescue Zone
|
||||
\w6. Camping
|
||||
7. Camp End
|
||||
\r8. Map Goal
|
||||
\w9. Jump
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yТип Вэйпоинта\w
|
||||
|
||||
1. Обычный
|
||||
\r2. Важный для Терров
|
||||
3. Важный для Ментов
|
||||
\w4. Лестница / Блок с Заложником
|
||||
\y5. Зона Спасения
|
||||
\w6. Кемперский
|
||||
7. Конец Кемперского
|
||||
\r8. Основная Точка
|
||||
\w9. Прыговой
|
||||
|
||||
\w0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yToggle Waypoint Flags\w
|
||||
|
||||
1. Block with Hostage
|
||||
2. Terrorists Specific
|
||||
3. CTs Specific
|
||||
4. Use Elevator
|
||||
5. Sniper Point (\yFor Camp Points Only!\w)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yИзменение Сигналов Вэйпоинтов\w
|
||||
|
||||
1. Блок с Заложником
|
||||
2. Только для Терров
|
||||
3. Только для Ментов
|
||||
4. Использовать Лифт
|
||||
5. Снайперский (\yТолько для кемперских точек!\w)
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yBot Command Menu\w
|
||||
|
||||
1. Make Double Jump
|
||||
2. Finish Double Jump
|
||||
|
||||
3. Drop the C4 Bomb
|
||||
4. Drop the Weapon
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yМеню Команд Бота\w
|
||||
|
||||
1. Сделать двойной Прыжок
|
||||
2. Закончить двойной Прыжок
|
||||
|
||||
3. Скинуть бомбу C4
|
||||
4. Скинуть пушку
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yAutoPath Distance\w
|
||||
|
||||
1. Distance 0
|
||||
2. Distance 100
|
||||
3. Distance 130
|
||||
4. Distance 160
|
||||
5. Distance 190
|
||||
6. Distance 220
|
||||
7. Distance 250 (Default)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yДистанция Автопути\w
|
||||
|
||||
1. Дистанция 0
|
||||
2. Дистанция 100
|
||||
3. Дистанция 130
|
||||
4. Дистанция 160
|
||||
5. Дистанция 190
|
||||
6. Дистанция 220
|
||||
7. Дистанция 250 (По умолчанию)
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
\yCreate Path (Choose Direction)\w
|
||||
|
||||
1. Outgoing Path
|
||||
2. Incoming Path
|
||||
3. Bidirectional (Both Ways)
|
||||
|
||||
0. Exit
|
||||
|
||||
[TRANSLATED]
|
||||
\yСоздание Пути (Выберите Направление)\w
|
||||
|
||||
1. Исходящий Путь
|
||||
2. Входящий Путь
|
||||
3. Бинаправленный (Оба Пути)
|
||||
|
||||
0. Выход
|
||||
|
||||
[ORIGINAL]
|
||||
Map not waypointed. Can't Create Bot
|
||||
|
||||
[TRANSLATED]
|
||||
У карты нет вэйпоинтов. Невозможно создать Бота.
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints has been changed. Load waypoints again...
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты были изменены. Загрузите их заново...
|
||||
|
||||
[ORIGINAL]
|
||||
Invalid skill given. Using random skill.
|
||||
|
||||
[TRANSLATED]
|
||||
Дан неверный скилл. Скилл будет выбран случайно.
|
||||
|
||||
[ORIGINAL]
|
||||
Connecting Bot...
|
||||
|
||||
[TRANSLATED]
|
||||
Присоединяю Бота...
|
||||
|
||||
[ORIGINAL]
|
||||
Fill Server with %s bots...
|
||||
|
||||
[TRANSLATED]
|
||||
Заполнение сервера с %s ботами...
|
||||
|
||||
[ORIGINAL]
|
||||
Bots are removed from server.
|
||||
|
||||
[TRANSLATED]
|
||||
Боты убраны с сервера.
|
||||
|
||||
[ORIGINAL]
|
||||
Bot '%s' kicked
|
||||
|
||||
[TRANSLATED]
|
||||
Бот '%s' убран
|
||||
|
||||
[ORIGINAL]
|
||||
\yBots Remove Menu (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. Back
|
||||
|
||||
[TRANSLATED]
|
||||
\yУбирание ботов (%d/4):\w
|
||||
|
||||
%s
|
||||
%s 0. Назад
|
||||
|
||||
[ORIGINAL]
|
||||
%s\d %1.1d. Not a Bot\w
|
||||
|
||||
[TRANSLATED]
|
||||
%s\d %1.1d. Не бот\w
|
||||
|
||||
[ORIGINAL]
|
||||
9. More...
|
||||
|
||||
|
||||
[TRANSLATED]
|
||||
9. Больше...
|
||||
|
||||
[ORIGINAL]
|
||||
All Bots died !
|
||||
|
||||
[TRANSLATED]
|
||||
Все боты убиты.
|
||||
|
||||
[ORIGINAL]
|
||||
%s weapon mode selected
|
||||
|
||||
[TRANSLATED]
|
||||
%s режим оружия выбран
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Source Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
ОШИБКА: Поиск Пути: Начало Ошибочно->%d
|
||||
|
||||
[ORIGINAL]
|
||||
ERROR: FindPath Destination Invalid->%d
|
||||
|
||||
[TRANSLATED]
|
||||
ОШИБКА: Поиск Пути: Назначение Ошибочно->%d
|
||||
|
||||
[ORIGINAL]
|
||||
Denied path creation from %d to %d (path already exists)
|
||||
|
||||
[TRANSLATED]
|
||||
Запрет создания пути из %d в %d (путь уже существует)
|
||||
|
||||
[ORIGINAL]
|
||||
Path added from %d to %d
|
||||
|
||||
[TRANSLATED]
|
||||
Путь добавлен из %d в %d
|
||||
|
||||
[ORIGINAL]
|
||||
This is not Camping Waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Это не кемперский Вэйпоинт
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint number out of range (Valid range From 0 to %d)
|
||||
|
||||
[TRANSLATED]
|
||||
Кол-во вэйпоинтов вышло за границы (Верная граница с 0 и до %d)
|
||||
|
||||
[ORIGINAL]
|
||||
Cannot connect waypoint to itself
|
||||
|
||||
[TRANSLATED]
|
||||
Невозможно соеденить вэйпоинт сам с собой
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d connected with invalid Waypoint #%d!
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинт %d соеденен с неверным Вэйпоинтом № %d!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d isn't connected with any other Waypoint!
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинт %d не соединен ни с одним другим вэйпоинтом
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d pathnumber differs from index!
|
||||
|
||||
[TRANSLATED]
|
||||
Количство путей вэйпоинтов %d несовпадает с его индексом!
|
||||
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint %d Camp-Endposition not set!
|
||||
|
||||
[TRANSLATED]
|
||||
На вэйпоинте %d ну установлен точка конца кемперства!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set a Rescue Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Ты не установил Зону спасения Заложников!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Terrorist Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Ты не установил ни одного важного для Терров Вэйпоинта!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any CT Important Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Ты не установил ни одного важного для Ментов Вэйпоинта!
|
||||
|
||||
[ORIGINAL]
|
||||
You didn't set any Goal Point!
|
||||
|
||||
[TRANSLATED]
|
||||
Ты не установил ни одного главного Вэйпоинта!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint #0 to Waypoint #%d!
|
||||
|
||||
[TRANSLATED]
|
||||
Путь испорчен из Вэйпоинта № 0 к Вэйпоинту № %d!
|
||||
|
||||
[ORIGINAL]
|
||||
Path broken from Waypoint #%d to Waypoint #0!
|
||||
|
||||
[TRANSLATED]
|
||||
Путь испорчен из Вэйпоинта № %d к Вэйпоинту № 0!
|
||||
|
||||
[ORIGINAL]
|
||||
Choose weapon from 1 to 7 range
|
||||
|
||||
[TRANSLATED]
|
||||
Выберите оружие в пределах от 1 до 7
|
||||
|
||||
[ORIGINAL]
|
||||
All dead bots will vote for map #%d
|
||||
|
||||
[TRANSLATED]
|
||||
Все мертвые боты будут голосовать за карту #%d
|
||||
|
||||
[ORIGINAL]
|
||||
Bot %s executing command %s
|
||||
|
||||
[TRANSLATED]
|
||||
Бот %s выполняет команду %s
|
||||
|
||||
[ORIGINAL]
|
||||
Player is NOT Bot!
|
||||
|
||||
[TRANSLATED]
|
||||
Игрок не БОТ!!!
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Включено редактирование Вэйпоинтов
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint Editing Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Редактирование Вэйпоинтов Выключено
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Режим полёта включен
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты Выключены
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints are Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты Включены
|
||||
|
||||
[ORIGINAL]
|
||||
Noclip Cheat Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Режим полёта выключен
|
||||
|
||||
[ORIGINAL]
|
||||
Showing Direction to Waypoint #%d
|
||||
|
||||
[TRANSLATED]
|
||||
Показываю направление к Вэйпоинту #%d
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints Saved
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты сохранены
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoints loaded
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты загружены
|
||||
|
||||
[ORIGINAL]
|
||||
Nodes work Fine
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты работают отлично
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint #%d now cached
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинт %d, теперь кеширован!
|
||||
|
||||
[ORIGINAL]
|
||||
Player '%s' teleported to waypoint #%d (x:%d, y:%d, z:%d)
|
||||
|
||||
[TRANSLATED]
|
||||
Игрок '%s' телепортирован на вэйпоинт #%d (x:%d, y:%d, z:%d)
|
||||
|
||||
[ORIGINAL]
|
||||
Experience tab saved
|
||||
|
||||
[TRANSLATED]
|
||||
Таблица опыта сохранена
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Enabled
|
||||
|
||||
[TRANSLATED]
|
||||
Опыт включен
|
||||
|
||||
[ORIGINAL]
|
||||
Experience Disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Опыт выключен
|
||||
|
||||
[ORIGINAL]
|
||||
Command not supported on dedicated server
|
||||
|
||||
[TRANSLATED]
|
||||
Команда не работает на выделенном сервере
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint not saved
|
||||
There are errors, see console
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинты не сохранены
|
||||
Есть ошибки, смотри консоль
|
||||
|
||||
[ORIGINAL]
|
||||
There are errors, see console
|
||||
|
||||
[TRANSLATED]
|
||||
Есть ошибки, смотри консоль
|
||||
|
||||
[ORIGINAL]
|
||||
You're dead, and have no access to this menu
|
||||
|
||||
[TRANSLATED]
|
||||
Ты мертв, и не имеешь доступа к этому меню
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath disabled
|
||||
|
||||
[TRANSLATED]
|
||||
Автопути отключены
|
||||
|
||||
[ORIGINAL]
|
||||
AutoPath maximum distance set to %f
|
||||
|
||||
[TRANSLATED]
|
||||
Максимальная дистанция автопути установлена в %f
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find nearest waypoint in 50 units
|
||||
|
||||
[TRANSLATED]
|
||||
Невозможно найти ближайший вэйпоинт на растоянии 50 юнитов
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to find destination waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Невозможно найти вэйпоинт назначения
|
||||
|
||||
[ORIGINAL]
|
||||
Unable to connect waypoint with itself
|
||||
|
||||
[TRANSLATED]
|
||||
Невозможно соеденить вэйпоинт сам с собой
|
||||
|
||||
[ORIGINAL]
|
||||
There is already no path on this waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
На этом вэйпоинте уже нет пути
|
||||
|
||||
[ORIGINAL]
|
||||
Cached waypoint cleared (nearby point not found in 50 units range)
|
||||
|
||||
[TRANSLATED]
|
||||
Сохраненный вэйпоинт удален (ближайший вэйпоинт не найден на растоянии 50 юнитов)
|
||||
|
||||
[ORIGINAL]
|
||||
Waypoint #%d has been put into memory
|
||||
|
||||
[TRANSLATED]
|
||||
Вэйпоинт №%d был запомнен
|
||||
|
||||
[ORIGINAL]
|
||||
Maximum players reached (%d/%d). Unable to create Bot.
|
||||
|
||||
[TRANSLATED]
|
||||
Максимум игроков добавлено (%d/%d). Невозможно создать Бота.
|
||||
|
||||
[ORIGINAL]
|
||||
Cannot assign sniper flag to waypoint #%d. This is not camp waypoint
|
||||
|
||||
[TRANSLATED]
|
||||
Невозможно добавить снайперский сигнал на вэйпоинт №%d. Вэйпоинт не кемперский
|
||||
339
cfg/addons/yapb/conf/lang/ru_names.cfg
Normal file
339
cfg/addons/yapb/conf/lang/ru_names.cfg
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: ru_names.cfg
|
||||
;
|
||||
; Configuration file contains Russian bot names.
|
||||
;
|
||||
|
||||
Deg omMOPO3
|
||||
nyrJIuBbIu JIbI>|<HuK
|
||||
aKTuBHbIu roMeC
|
||||
yCaTbIu ToKaPb
|
||||
C4aCTJIuBbIu JIyneHb
|
||||
BeCeJIbIu 4eKuCT
|
||||
HeXuJIbIu TaHKuCT
|
||||
CaguCT-3aTeuHuK
|
||||
Hego6pbIu JIeKaPb
|
||||
MaCTeP XegoB
|
||||
6PoHeTeMKuH noHoCeU,
|
||||
CepguTbIu 3y6PuK
|
||||
CoHJIuBbIu BuKuHr
|
||||
3Meu ropbIHbI4
|
||||
ra3oHoKocuJIbLLI,uK
|
||||
Xy>I<e_JIoJIKu
|
||||
~BuHHu_nyK~
|
||||
Ba3eJIuHoBbIu My>I<uK
|
||||
6ypaTuHo
|
||||
/7a/7a_KapJIo
|
||||
My>|<u4oK CJIOHoBu4oK
|
||||
>|<eCTKuu_4e6yp
|
||||
KpbIca KaMuKag3e
|
||||
KoH4eHbIu ypog
|
||||
He3gopoBbIu ncux
|
||||
ommonbIpeHbIu ynbIPb
|
||||
CKyKo>|<eHbIu E>I<
|
||||
nu>|<oH c Ho>|<oM
|
||||
CyKa-B-6oTaX
|
||||
3apa3a B Ta3e
|
||||
KocMoHaBT Ha KaMa3e
|
||||
// eol 32 names
|
||||
|
||||
[baz] DeCaHmHuK
|
||||
uHCneKToP
|
||||
BbIcTpeJI B >I<ony!
|
||||
DupeKTop_KyKypy3HuKa
|
||||
Cep>I<aHm
|
||||
Ha4aJIbHuK KapmbI
|
||||
y4uTeJIb XuMuu
|
||||
>I<apeHbIu neTyX
|
||||
BaMnup
|
||||
6oT 6a3uJIuo
|
||||
TepMuHaTop
|
||||
Kapa6aC PaCKoJI6aC
|
||||
[oMoH]~noKeMoH
|
||||
[+Duracell-]
|
||||
Oo!oO
|
||||
MegBe>I<oHoK -)MKa
|
||||
PbI6oKon
|
||||
CynePKpoBo>I<agHbIu
|
||||
g>I<eKu 4aH
|
||||
KOT-B-POMALLIKAX
|
||||
Bcex-nopBy!
|
||||
CmpaHHbIu CmpaHHuK
|
||||
yJIbI6o4HbIu 6oT
|
||||
[RWL] BoBa KoMaTo3HuK
|
||||
[RWL] LLIHULLEJIb
|
||||
[RWL] Ado
|
||||
[RWL] dur5t
|
||||
[RWL] SAOPP Family
|
||||
[RWL] Deni$OK
|
||||
IOHbIu 3agpoT.
|
||||
NetManiac
|
||||
CmapuK-noxa6bI4
|
||||
KoMaToZZzz
|
||||
Kyu >I<eJIe3HbIu
|
||||
[HSH] KyMapuK
|
||||
uBaH KpuBopyKoB
|
||||
>PartiZan<
|
||||
3JIo6HbIu yXaPb
|
||||
=ReANiMaToR=
|
||||
OTMoPo>I<eHbIu MuHTau
|
||||
nPanoP KoHeB
|
||||
4yKoTcKuu CHauneP
|
||||
[dnb] BASSBOMB
|
||||
noHb KugaJIbHbIu
|
||||
cccp| =LENIN=
|
||||
SHiBZDiK
|
||||
BOP_B_3anoE
|
||||
Mo3roEg
|
||||
Mauop KyMaP
|
||||
uHCneKToP >I<onuH
|
||||
KpoBaBbIu neKaPb
|
||||
XMyPbIu >I<MyPuK
|
||||
3JIoCTHbIu nePgyH
|
||||
CuBbIu gyPeHb
|
||||
z00m
|
||||
K!110grAmm
|
||||
jaZzK!ll
|
||||
KeKS| PerDoLetto
|
||||
KeKS| KyKyM6a
|
||||
KeKS| Co6aKa-PeKC
|
||||
KeKS| ZeliBoBa
|
||||
BoJIoCaTbIe Ho3gPu
|
||||
6yXou MATPOC
|
||||
CocucbKa
|
||||
CbIH_OTMoPo3Ka
|
||||
CTaPuK OTMoPo3oK
|
||||
KpuBou PaxuT KyKyeB
|
||||
KpyTou nep4uK~
|
||||
3JIou TapaKaH
|
||||
Heu3BecmHbIu
|
||||
HoBoXygoHocop
|
||||
rpy3oBuK C HaBo3oM
|
||||
OrpbI3oK
|
||||
6apbIra
|
||||
Ky3bKuHa_MaTb
|
||||
CaHuTaP u3 Mopra
|
||||
KyJIuHaP TeCaKoB
|
||||
noJIy4u_B_>I<6aH
|
||||
KoMaPuK
|
||||
ne4aJIbHbIu 4auHuK
|
||||
::M4N`o`W4R::
|
||||
P1nc ZoMBy
|
||||
>I<bIPHbIu nuHrBuH
|
||||
SchtandartenFuhrer
|
||||
ST4L!N RuL!T
|
||||
B.B./7ymuH
|
||||
4ePHbIu JIeKToP.
|
||||
naHKu_B_TAHKE
|
||||
Kampers in Pampers
|
||||
OTJIu4HbIu_nuHr!
|
||||
napa nCuXoJIoroB
|
||||
KoBapHoe JIaMo
|
||||
4e6ypeK @(o,o)@
|
||||
He>I<Ha9I JIaMKa
|
||||
geg Ma3gau
|
||||
HeonbITHbIu /7ana
|
||||
/7poDOOMaHHbIu III
|
||||
3BePCKuu_4uT0P
|
||||
=| ReAnimaToR |=
|
||||
Ky3bMu4b
|
||||
TelepuzO
|
||||
Tynou KyPCaHT
|
||||
XogoK 3a /7uBoM
|
||||
DEADushka MoroZ
|
||||
mu1ti-K!ll
|
||||
Ne0
|
||||
ToJIna areHToB CMuToB
|
||||
=ZL0Y=
|
||||
HeadKilla ==(oo)=>
|
||||
))==0KyHb=%>
|
||||
laZar
|
||||
=| Zar |=
|
||||
DeD LoGoPeD
|
||||
|z| QuaZatron.
|
||||
|z| NecromanZer.
|
||||
|z| Zerg.
|
||||
|z| teZer
|
||||
[z] *moZg*
|
||||
/z/ Z-Lum!noFor
|
||||
[dnb] dub
|
||||
[dnb] Kara
|
||||
(dnb) Mechano!d
|
||||
dnb| 3v!LKilla
|
||||
4ygHbIu /7anopomHuK
|
||||
XuTPbIu_AHyC
|
||||
Xo66uT
|
||||
[baz] GAD
|
||||
[baz] K/IoH
|
||||
[baz] viz0r
|
||||
[baz] MiXa
|
||||
|baz| go6pbIu 6o6puK
|
||||
|baz| DiGGeR
|
||||
|baz| =GRoMoZeKA=
|
||||
|baz| BuHToBKuH
|
||||
|baz| ZveroBoy
|
||||
SK| ahl.
|
||||
SK| bds.
|
||||
SK| brunk
|
||||
SK| ElemenT
|
||||
SK| fisker
|
||||
SK| goseY
|
||||
SK| HeatoN
|
||||
SK| Potti
|
||||
Morda
|
||||
6oM>I<yaH
|
||||
n0name| Haru6aToP
|
||||
KyJIbHbIu_PyJIe3
|
||||
NiTron
|
||||
[.71]TPAXTOP
|
||||
M19*KaLbI4
|
||||
M19*Rado
|
||||
M19*NooK
|
||||
M19*MadFan
|
||||
M19*Rider
|
||||
forZe| Xen1tron
|
||||
[forZe] iTuman
|
||||
forZe| Electric.eYe
|
||||
forZe| Romashka
|
||||
[forZe] h0s7
|
||||
[team9] vesslan
|
||||
[team9] XeqtR
|
||||
[team9] Luciano
|
||||
[team9] quick
|
||||
[team9] Luccese
|
||||
6bIK
|
||||
StabiliZat0R
|
||||
yHuKaJIbHbIu yHuTa3
|
||||
MegaCamper
|
||||
KoT MaTPOCKuH
|
||||
L1MoN
|
||||
Bo>|<gb /7oKeMoHoB
|
||||
[s!L3nt]xen0b1te
|
||||
Xeg-XegbI4
|
||||
=XAM=
|
||||
loloboto
|
||||
L0M
|
||||
FluroGinecolog
|
||||
-papique-
|
||||
CyKaHax
|
||||
Be>I<JIuBbIu JIOCb
|
||||
CTago CJIoHoB
|
||||
yKypbILLI
|
||||
OTCTou CJIuBo4HbIu
|
||||
>>>BullDoZzeR
|
||||
=geCePT=
|
||||
PROVOCATOR
|
||||
Tpyn
|
||||
ZLOid
|
||||
MygaK C Py>I<beM
|
||||
DiGGeR
|
||||
-MAM6A-
|
||||
KeHToyKJIag4uK
|
||||
nanuK
|
||||
-ZerG-
|
||||
MYX0M0P
|
||||
neC MoXHoPbIJIbIu
|
||||
-PerfoRaToR->
|
||||
neJlbMeHb
|
||||
V!C
|
||||
g00dDayToD!e
|
||||
poccoMaxa
|
||||
K!llogr4mm
|
||||
geM6eJIb
|
||||
MyXa
|
||||
Davilka
|
||||
CTaJIbHbIe TanKu
|
||||
CJIoHeHoK
|
||||
**3y6P**
|
||||
ronHuK
|
||||
-=y6uBaToP=-
|
||||
BJIaCTeJIuH KoHTPbI
|
||||
MaKaPoHHuK
|
||||
Mekhano!d
|
||||
**BE45t**
|
||||
gollum
|
||||
noCMoTPuM KTo 4Mo
|
||||
onaCHbIu Tun
|
||||
B.B.TynuH
|
||||
-=AMnyTaToP=-
|
||||
**Natashka**
|
||||
neraJIb
|
||||
MopCKou_CBuH
|
||||
CTenHou OXoTHuK
|
||||
Ky4Ka
|
||||
-##.NeO.##-
|
||||
Vasily Pupkin
|
||||
gpo6ogyH C 6ogyHa
|
||||
KoBaPHbIu roMuK
|
||||
Ca6JIe3y6a9I >I<y4Ka
|
||||
4un u geuJI
|
||||
roBHogaB4uK
|
||||
BoB4uK
|
||||
CaM_gyPaK
|
||||
TuTbKa
|
||||
KoHb B Canorax
|
||||
9I_4eLLIKa-o6op>I<oTeCb!
|
||||
3JIa9I 4eLLIKa
|
||||
Ky6uK Bpy6uK
|
||||
KJIaCCHbIe CuCbKu
|
||||
XOPb C gy6uHou
|
||||
CTaJIbHbIe 9IuKu
|
||||
pardoN-Zaperdon
|
||||
npocmo HanpocTo
|
||||
He y6uBauTe Cpa3y!
|
||||
MaLLIa-KaKaLLIa
|
||||
3a6er_ge6uJIoB
|
||||
3agHenpoXog4uK
|
||||
KPaCHbIu KPoKoguJI
|
||||
CMeJIbIu g9ITeJI
|
||||
4y4yHgpuK
|
||||
Po3oBa9I nonKa
|
||||
PagoCTHa9I CoCKA
|
||||
6yKa-nyKa
|
||||
BeJIuKuu HaCoCbHuK
|
||||
KoHKpeTHa9I TynKa
|
||||
DP9IHb
|
||||
rJIoTaTEJIb noPTBEuHa
|
||||
AFPuKAHeu,
|
||||
6PI-0C KoJIdyH
|
||||
}I{uD
|
||||
KBA3uMODA
|
||||
MukJIyXA
|
||||
TBaPb
|
||||
TaHu,yI-0LLIuE BoDoJIa3bI
|
||||
HeBuHHbIu` TyHeu,
|
||||
JIyHHbIu BCaDHuK
|
||||
6oJIbHOu LLIaP
|
||||
npu3pak nuHokuo
|
||||
6oM6a-MOJI
|
||||
TaHeu, MAJIeHbKux CBeHEu
|
||||
u,BeTHbIe ry6bI
|
||||
Tpy-JI9I-JI9I
|
||||
TaHro Ha o6JIaKe
|
||||
CnePMATo3aBP 4eMnuoH
|
||||
DOM roJIy6bIe rJIa3a
|
||||
ÂeceJIbIu AHCAM6JIb
|
||||
nPoCHuCb HAC o6oKpaJIu
|
||||
6ercTBo (KoHb)
|
||||
ÑTPEMHbIu KOPA6JIb
|
||||
DbIM u neneJI
|
||||
FAMuJIHbIu` BAMnuP
|
||||
MycoPHbIu BETEP
|
||||
-)poTu4ecKue MOHCTPbI
|
||||
6eJIbIe CTOJI6bI
|
||||
OrHEHHa9I rueHa
|
||||
npopok Ha kapyceJIu
|
||||
KpbIJIATbIE CJIOHbI
|
||||
MHoro 6akcoB
|
||||
FaHTuK
|
||||
O4Ku-Dypa4Ku
|
||||
}I{udKuu` CTyJI
|
||||
y4e6Huk no 6puTBe
|
||||
uLLI,y Pa6oTy (1000$)
|
||||
o6LLIuPHbIu` B3pbIB
|
||||
u,BeTHou` 6yKeT
|
||||
3uJIu6o6a - !nuBo
|
||||
CaDo-Ma3o-nJIeTka!
|
||||
21
cfg/addons/yapb/conf/logos.cfg
Normal file
21
cfg/addons/yapb/conf/logos.cfg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: logos.cfg
|
||||
;
|
||||
; Configuration file contains logos definitions for bots.
|
||||
; They are taken from decals.wad.
|
||||
;
|
||||
|
||||
{biohaz
|
||||
{graf003
|
||||
{graf004
|
||||
{graf005
|
||||
{lambda06
|
||||
{target
|
||||
{hand1
|
||||
{spit2
|
||||
{bloodhand6
|
||||
{foot_l
|
||||
{foot_r
|
||||
81
cfg/addons/yapb/conf/weapon.cfg
Normal file
81
cfg/addons/yapb/conf/weapon.cfg
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
;
|
||||
; @package: YaPB
|
||||
; @version: 4.0
|
||||
; @author: YaPB Development Team
|
||||
; @filename: weapon.cfg
|
||||
;
|
||||
; Configuration file contains weapon preferences for bots.
|
||||
;
|
||||
|
||||
; Numbering of the weapons:
|
||||
; 0 - KNIFE
|
||||
; 1 - USP
|
||||
; 2 - GLOCK18
|
||||
; 3 - DEAGLE
|
||||
; 4 - P228
|
||||
; 5 - ELITE
|
||||
; 6 - FIVESEVEN
|
||||
; 7 - M3
|
||||
; 8 - XM1014
|
||||
; 9 - MP5NAVY
|
||||
; 10 - TMP
|
||||
; 11 - P90
|
||||
; 12 - MAC10
|
||||
; 13 - UMP45
|
||||
; 14 - AK47
|
||||
; 15 - SG552
|
||||
; 16 - M4A1
|
||||
; 17 - GALIL
|
||||
; 18 - FAMAS
|
||||
; 19 - AUG
|
||||
; 20 - SCOUT
|
||||
; 21 - AWP
|
||||
; 22 - G3SG1
|
||||
; 23 - SG550
|
||||
; 24 - M249
|
||||
; 25 - SHIELD
|
||||
|
||||
;
|
||||
; Following are Tables which specify which Team is allowed
|
||||
; to buy a weapon on a Map. You can also use it to allow/disallow
|
||||
; Weapons for a Team or a Map/Gamemode (remember that some
|
||||
; Weapons are team-specific and can't be bought by another team).
|
||||
; -1 = Disallow Buying for any Team
|
||||
; 0 = Terrorist Team only
|
||||
; 1 = CT Team only
|
||||
; 2 = Can be bought by both Teams
|
||||
; Standard Weapon Tab for CS & DE Maps
|
||||
;
|
||||
MapStandard = -1,0,-1,2,-1,0,1,2,2,2,-1,2,-1,-1,0,0,1,0,1,1,2,2,0,1,2,1
|
||||
MapAS = -1,-1,-1,2,-1,0,1,1,1,1,1,1,0,2,0,-1,1,0,1,1,0,0,-1,1,1,1
|
||||
|
||||
;
|
||||
; Grenade buying percentage
|
||||
; HE, FL, SMOKE
|
||||
;
|
||||
GrenadePercent = 98,75,60
|
||||
|
||||
;
|
||||
; Bot Economics. From left to right.
|
||||
;
|
||||
; 1 - If bot's money more than the value specified here. He can buy the primary weapon.
|
||||
; 2 - If bot's money more than the value specified here he will not buy SMGs (MP5, MAC10, TMP, P90, UMP45, SCOUT) (only for CTs) (+ 8/9/10)
|
||||
; 3 - If bot's money more than the value specified here it will not buy SMGs (MP5, MAC10, TMP, P90, UMP45, SCOUT) (only for Ts) (+ 8/9/10))
|
||||
; 4 - If bot's money more than the value specified here he can buy shotguns (M3, XM1014).
|
||||
; 5 - If bot's money less than the value specified here he cannot buy shotguns (M3, XM1014).
|
||||
; 6 - If bot's money more than the value specified here he can buy AWM, SG550, G3SG1, M249.
|
||||
; 7 - If bot's money less than the value specified here he cannot buy AWM, SG550, G3SG1, M249.
|
||||
; 8 - How much money bot leaves a prostock, at purchase of the primary weapon (only for type of behaviour - Normal)
|
||||
; 9 - How much money bot leaves a prostock, at purchase of the primary weapon (only for type of behaviour - Agressive).
|
||||
; 10 - How much money bot leaves a prostock, at purchase of the primary weapon (only for type of behaviour - Careful).
|
||||
; 11 - If bot's money more than the value specified here. He can buy the shield.
|
||||
;
|
||||
Economics = 1550,2100,2100,4000,6000,7000,16000,1200,800,1100,3000
|
||||
|
||||
;
|
||||
; The following Tables stores the Weapon Priorities of the Bots depending on
|
||||
; Personality (it affects buying & picking up better weapons from the ground).
|
||||
;
|
||||
PersonalityNormal = 00,02,01,04,05,06,03,12,10,24,25,13,11,08,07,22,23,20,21,09,19,15,17,18,14,16
|
||||
PersonalityRusher = 00,02,04,05,01,06,03,24,25,22,23,20,10,12,13,07,08,21,11,09,15,19,17,18,16,14
|
||||
PersonalityCareful = 00,02,01,04,05,06,03,07,08,12,10,13,11,09,18,17,15,19,16,14,20,22,25,23,24,21
|
||||
354
cfg/addons/yapb/conf/yapb.cfg
Normal file
354
cfg/addons/yapb/conf/yapb.cfg
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
//
|
||||
// @package: YaPB
|
||||
// @version: 4.0
|
||||
// @author: YaPB Development Team
|
||||
// @filename: yapb.cfg
|
||||
//
|
||||
// YAPB main configuration file. Can be executed via "exec" command.
|
||||
//
|
||||
|
||||
//
|
||||
// Enables or disables useful messages about bot states. Not required for end users
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "4"
|
||||
//
|
||||
yb_debug "0"
|
||||
|
||||
//
|
||||
// Forces all alive bots to build path and go to the specified here graph node.
|
||||
// ---
|
||||
// Default: "-1", Min: "-1", Max: "2048"
|
||||
//
|
||||
yb_debug_goal "-1"
|
||||
|
||||
//
|
||||
// Specifies the percent of bots, than can follow leader on each round start.
|
||||
// ---
|
||||
// Default: "20", Min: "0", Max: "100"
|
||||
//
|
||||
yb_user_follow_percent "20"
|
||||
|
||||
//
|
||||
// Specifies how many bots can follow a single user.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "16"
|
||||
//
|
||||
yb_user_max_followers "1"
|
||||
|
||||
//
|
||||
// If enabled, all bots will be forced only the knife, skipping weapon buying routines.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_jasonmode "0"
|
||||
|
||||
//
|
||||
// Allows bots to use radio or chattter.
|
||||
// Allowed values: '0', '1', '2'.
|
||||
// If '0', radio and chatter is disabled.
|
||||
// If '1', only radio allowed.
|
||||
// If '2' chatter and radio allowed.
|
||||
// ---
|
||||
// Default: "2", Min: "0", Max: "2"
|
||||
//
|
||||
yb_radio_mode "2"
|
||||
|
||||
//
|
||||
// Specifies whether bots able to use team economics, like do not buy any weapons for whole team to keep money for better guns.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_economics_rounds "1"
|
||||
|
||||
//
|
||||
// Sepcifies whether bots able to use 'shift' if they thinks that enemy is near.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_walking_allowed "1"
|
||||
|
||||
//
|
||||
// Allows or disallows bots to camp. Doesn't affects bomb/hostage defending tasks
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_camping_allowed "1"
|
||||
|
||||
//
|
||||
// Allows or disallows bots to take revenge of teamkillers / team attacks.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_tkpunish "1"
|
||||
|
||||
//
|
||||
// If enables bots think function is disabled, so bots will not move anywhere from their spawn spots.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_freeze_bots "0"
|
||||
|
||||
//
|
||||
// Allows or disallows the use of spay paints.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_spraypaints "1"
|
||||
|
||||
//
|
||||
// Allows or disallows bots weapon buying routines.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_botbuy "1"
|
||||
|
||||
//
|
||||
// Allows bots to destroy breakables around him, even without touching with them.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_destroy_breakables_around "1"
|
||||
|
||||
//
|
||||
// Specifies the paths for the bot chatter sound files.
|
||||
// ---
|
||||
// Default: "sound/radio/bot"
|
||||
//
|
||||
yb_chatter_path "sound/radio/bot"
|
||||
|
||||
//
|
||||
// Specifies semicolon separated list of weapons that are not allowed to buy / pickup.
|
||||
// ---
|
||||
// Default: ""
|
||||
//
|
||||
yb_restricted_weapons ""
|
||||
|
||||
//
|
||||
// Enables or disables bots chat functionality.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_chat "1"
|
||||
|
||||
//
|
||||
// Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.
|
||||
// ---
|
||||
// Default: "2", Min: "0", Max: "3"
|
||||
//
|
||||
yb_shoots_thru_walls "2"
|
||||
|
||||
//
|
||||
// Enables or disables searching world for enemies.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_ignore_enemies "0"
|
||||
|
||||
//
|
||||
// Enables or disables checking enemy rendering flags. Useful for some mods.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_check_enemy_rendering "0"
|
||||
|
||||
//
|
||||
// Enables or disables bot ability to stab the enemy with knife if bot is in good condition.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_stab_close_enemies "1"
|
||||
|
||||
//
|
||||
// Enables or disables display menu text, when players asks for menu. Useful only for Android.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_display_menu_text "1"
|
||||
|
||||
//
|
||||
// The value (password) for the setinfo key, if user set's correct password, he's gains access to bot commands and menus.
|
||||
// ---
|
||||
// Default: ""
|
||||
//
|
||||
yb_password ""
|
||||
|
||||
//
|
||||
// The name of setinfo key used to store password to bot commands and menus
|
||||
// ---
|
||||
// Default: "_ybpw"
|
||||
//
|
||||
yb_password_key "_ybpw"
|
||||
|
||||
//
|
||||
// Enables or disables CSDM / FFA mode for bots.
|
||||
// Allowed values: '0', '1', '2', '3'.
|
||||
// If '0', CSDM / FFA mode is auto-detected.
|
||||
// If '1', CSDM mode is enabled, but FFA is disabled.
|
||||
// If '2' CSDM and FFA mode is enabled.
|
||||
// If '3' CSDM and FFA mode is disabled.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "3"
|
||||
//
|
||||
yb_csdm_mode "0"
|
||||
|
||||
//
|
||||
// Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_graph_fixcamp "1"
|
||||
|
||||
//
|
||||
// Specifies the URL from bots will be able to download graph in case of missing local one.
|
||||
// ---
|
||||
// Default: "http://graph.yapb.ru/"
|
||||
//
|
||||
yb_graph_url "http://graph.yapb.ru/"
|
||||
|
||||
//
|
||||
// Kick bots to automatically make room for human players.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_autovacate "1"
|
||||
|
||||
//
|
||||
// Bind's specified key for openining bots menu.
|
||||
// ---
|
||||
// Default: "="
|
||||
//
|
||||
yb_bind_menu_key "="
|
||||
|
||||
//
|
||||
// Specifies the number bots to be added to the game.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "32"
|
||||
//
|
||||
yb_quota "12"
|
||||
|
||||
//
|
||||
// Specifies the type of quota.
|
||||
// Allowed values: 'normal', 'fill', and 'match'.
|
||||
// If 'fill', the server will adjust bots to keep N players in the game, where N is cv_quota.
|
||||
// If 'match', the server will maintain a 1:N ratio of humans to bots, where N is cv_quota_match.
|
||||
// ---
|
||||
// Default: "normal"
|
||||
//
|
||||
yb_quota_mode "normal"
|
||||
|
||||
//
|
||||
// Number of players to match if cv_quota_mode set to 'match'
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "32"
|
||||
//
|
||||
yb_quota_match "0"
|
||||
|
||||
//
|
||||
// Specifies hou many times per second bot code will run.
|
||||
// ---
|
||||
// Default: "30.0", Min: "30.0", Max: "90.0"
|
||||
//
|
||||
yb_think_fps "30.0"
|
||||
|
||||
//
|
||||
// Specifies amount of time in seconds when bots will be killed if no humans left alive.
|
||||
// ---
|
||||
// Default: "0.0", Min: "0.0", Max: "90.0"
|
||||
//
|
||||
yb_autokill_delay "0.0"
|
||||
|
||||
//
|
||||
// Sepcifies whether bots should join server, only when at least one human player in game.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_join_after_player "0"
|
||||
|
||||
//
|
||||
// Forces all bots to join team specified here.
|
||||
// ---
|
||||
// Default: "any"
|
||||
//
|
||||
yb_join_team "any"
|
||||
|
||||
//
|
||||
// Specifies after how many seconds bots should start to join the game after the changelevel.
|
||||
// ---
|
||||
// Default: "5.0", Min: "0.0", Max: "30.0"
|
||||
//
|
||||
yb_join_delay "5.0"
|
||||
|
||||
//
|
||||
// All the bot names will be prefixed with string specified with this cvar.
|
||||
// ---
|
||||
// Default: ""
|
||||
//
|
||||
yb_name_prefix ""
|
||||
|
||||
//
|
||||
// All bots difficulty level. Chaning at runtime will affect already created bots.
|
||||
// ---
|
||||
// Default: "4", Min: "0", Max: "4"
|
||||
//
|
||||
yb_difficulty "4"
|
||||
|
||||
//
|
||||
// Enables or disabels displaying bot avatars in front of their names in scoreboard. Note, that is currently you can see only avatars of your steam friends.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_show_avatars "1"
|
||||
|
||||
//
|
||||
// Enables latency display in scoreboard.
|
||||
// Allowed values: '0', '1', '2'.
|
||||
// If '0', there is nothing displayed.
|
||||
// If '1', there is a 'BOT' is displayed.
|
||||
// If '2' fake ping is displayed.
|
||||
// ---
|
||||
// Default: "2", Min: "0", Max: "2"
|
||||
//
|
||||
yb_show_latency "2"
|
||||
|
||||
//
|
||||
// Specifies the language for bot messages and menus.
|
||||
// ---
|
||||
// Default: "en"
|
||||
//
|
||||
yb_language "en"
|
||||
|
||||
//
|
||||
// Specifies comma separated list of bot cvars, that will not be overriten by config on changelevel.
|
||||
// ---
|
||||
// Default: "yb_quota,yb_autovacate"
|
||||
//
|
||||
yb_ignore_cvars_on_changelevel "yb_quota,yb_autovacate"
|
||||
|
||||
//
|
||||
// Enables or disables extra hard difficulty for bots.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "1"
|
||||
//
|
||||
yb_whose_your_daddy "0"
|
||||
|
||||
//
|
||||
// Selects the heuristic function mode. For debug purposes only.
|
||||
// ---
|
||||
// Default: "0", Min: "0", Max: "4"
|
||||
//
|
||||
yb_debug_heuristic_type "0"
|
||||
|
||||
//
|
||||
// Enables or disables showing welcome message to host entity on game start.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_display_welcome_text "1"
|
||||
|
||||
//
|
||||
// Enables or disabled fake server queries response, that shows bots as real players in server browser.
|
||||
// ---
|
||||
// Default: "1", Min: "0", Max: "1"
|
||||
//
|
||||
yb_enable_query_hook "1"
|
||||
|
||||
92
ext/crlib/cr-alloc.h
Normal file
92
ext/crlib/cr-alloc.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// default allocator for cr-objects
|
||||
class Allocator : public Singleton <Allocator> {
|
||||
public:
|
||||
Allocator () = default;
|
||||
~Allocator () = default;
|
||||
|
||||
public:
|
||||
template <typename T> T *allocate (const size_t length = 1) {
|
||||
auto ptr = reinterpret_cast <T *> (malloc (length * sizeof (T)));
|
||||
|
||||
if (!ptr) {
|
||||
plat.abort ();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T> void deallocate (T *memory) {
|
||||
free (memory);
|
||||
memory = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> void construct (T *memory, Args &&...args) {
|
||||
new (memory) T (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <typename T> void destruct (T *memory) {
|
||||
memory->~T ();
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> T *create (Args &&...args) {
|
||||
auto d = allocate <T> ();
|
||||
new (d) T (cr::forward <Args> (args)...);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename T> T *createArray (const size_t amount) {
|
||||
auto memory = allocate <T> (amount);
|
||||
|
||||
for (size_t i = 0; i < amount; ++i) {
|
||||
new (memory + i) T ();
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> void destroy (T *memory) {
|
||||
if (memory) {
|
||||
destruct (memory);
|
||||
deallocate (memory);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Allocator, alloc);
|
||||
|
||||
template <typename T> class UniquePtr;
|
||||
|
||||
// implment singleton with UniquePtr
|
||||
template <typename T> T &Singleton <T>::instance () {
|
||||
static const UniquePtr <T> instance_ { alloc.create <T> () };
|
||||
return *instance_;
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -25,10 +32,10 @@ CR_NAMESPACE_BEGIN
|
|||
|
||||
// simple array class like std::vector
|
||||
template <typename T, ReservePolicy R = ReservePolicy::Multiple, size_t S = 0> class Array : public DenyCopying {
|
||||
public:
|
||||
T *m_data = nullptr;
|
||||
size_t m_capacity = 0;
|
||||
size_t m_length = 0;
|
||||
private:
|
||||
T *m_data {};
|
||||
size_t m_capacity {};
|
||||
size_t m_length {};
|
||||
|
||||
public:
|
||||
explicit Array () {
|
||||
|
|
@ -102,8 +109,10 @@ public:
|
|||
}
|
||||
auto data = alloc.allocate <T> (capacity);
|
||||
|
||||
transferElements (data, m_data, m_length);
|
||||
alloc.deallocate (m_data);
|
||||
if (m_data) {
|
||||
transferElements (data, m_data, m_length);
|
||||
alloc.deallocate (m_data);
|
||||
}
|
||||
|
||||
m_data = data;
|
||||
m_capacity = capacity;
|
||||
|
|
@ -137,8 +146,8 @@ public:
|
|||
return reserve (amount - m_length);
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return m_length;
|
||||
template <typename U = size_t> U length () const {
|
||||
return static_cast <U> (m_length);
|
||||
}
|
||||
|
||||
size_t capacity () const {
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -86,12 +93,18 @@ public:
|
|||
};
|
||||
|
||||
// singleton for objects
|
||||
template <typename T> struct Singleton : private DenyCopying {
|
||||
template<typename T> class Singleton : public DenyCopying {
|
||||
protected:
|
||||
Singleton ()
|
||||
{ }
|
||||
|
||||
public:
|
||||
static T &get () {
|
||||
static T ref_;
|
||||
return ref_;
|
||||
};
|
||||
static T &instance (); // implemented in cr-alloc.h
|
||||
|
||||
public:
|
||||
T *operator -> () {
|
||||
return &instance ();
|
||||
}
|
||||
};
|
||||
|
||||
// simple scoped enum, instaed of enum class
|
||||
|
|
@ -112,8 +125,8 @@ public:
|
|||
CR_DECLARE_SCOPED_ENUM_TYPE(enumName, int32, __VA_ARGS__) \
|
||||
|
||||
// exposes global variable from class singleton
|
||||
#define CR_EXPOSE_GLOBAL_SINGLETON(className, variable) \
|
||||
static auto &variable = className::get () \
|
||||
#define CR_EXPOSE_GLOBAL_SINGLETON(className, variable) \
|
||||
static auto &variable = className::instance () \
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -15,22 +22,22 @@ CR_NAMESPACE_BEGIN
|
|||
// simple priority queue
|
||||
template <typename T> class BinaryHeap final : public DenyCopying {
|
||||
private:
|
||||
Array <T> m_data;
|
||||
Array <T> contents_;
|
||||
|
||||
public:
|
||||
explicit BinaryHeap () = default;
|
||||
|
||||
BinaryHeap (BinaryHeap &&rhs) noexcept : m_data (cr::move (rhs.m_data))
|
||||
BinaryHeap (BinaryHeap &&rhs) noexcept : contents_ (cr::move (rhs.contents_))
|
||||
{ }
|
||||
|
||||
~BinaryHeap () = default;
|
||||
|
||||
public:
|
||||
template <typename U> bool push (U &&item) {
|
||||
if (!m_data.push (cr::move (item))) {
|
||||
if (!contents_.push (cr::move (item))) {
|
||||
return false;
|
||||
}
|
||||
size_t length = m_data.length ();
|
||||
const size_t length = contents_.length ();
|
||||
|
||||
if (length > 1) {
|
||||
percolateUp (length - 1);
|
||||
|
|
@ -39,10 +46,10 @@ public:
|
|||
}
|
||||
|
||||
template <typename ...Args> bool emplace (Args &&...args) {
|
||||
if (!m_data.emplace (cr::forward <Args> (args)...)) {
|
||||
if (!contents_.emplace (cr::forward <Args> (args)...)) {
|
||||
return false;
|
||||
}
|
||||
size_t length = m_data.length ();
|
||||
const size_t length = contents_.length ();
|
||||
|
||||
if (length > 1) {
|
||||
percolateUp (length - 1);
|
||||
|
|
@ -51,17 +58,17 @@ public:
|
|||
}
|
||||
|
||||
const T &top () const {
|
||||
return m_data[0];
|
||||
return contents_[0];
|
||||
}
|
||||
|
||||
T pop () {
|
||||
if (m_data.length () == 1) {
|
||||
return m_data.pop ();
|
||||
if (contents_.length () == 1) {
|
||||
return contents_.pop ();
|
||||
}
|
||||
auto key (cr::move (m_data[0]));
|
||||
auto key (cr::move (contents_[0]));
|
||||
|
||||
m_data[0] = cr::move (m_data.last ());
|
||||
m_data.discard ();
|
||||
contents_[0] = cr::move (contents_.last ());
|
||||
contents_.discard ();
|
||||
|
||||
percolateDown (0);
|
||||
return key;
|
||||
|
|
@ -69,24 +76,24 @@ public:
|
|||
|
||||
public:
|
||||
size_t length () const {
|
||||
return m_data.length ();
|
||||
return contents_.length ();
|
||||
}
|
||||
|
||||
bool empty () const {
|
||||
return !m_data.length ();
|
||||
return !contents_.length ();
|
||||
}
|
||||
|
||||
void clear () {
|
||||
m_data.clear ();
|
||||
contents_.clear ();
|
||||
}
|
||||
|
||||
private:
|
||||
void percolateUp (size_t index) {
|
||||
while (index != 0) {
|
||||
size_t parentIndex = parent (index);
|
||||
const size_t parentIndex = parent (index);
|
||||
|
||||
if (m_data[parentIndex] > m_data[index]) {
|
||||
cr::swap (m_data[index], m_data[parentIndex]);
|
||||
if (contents_[parentIndex] > contents_[index]) {
|
||||
cr::swap (contents_[index], contents_[parentIndex]);
|
||||
index = parentIndex;
|
||||
}
|
||||
else {
|
||||
|
|
@ -100,15 +107,15 @@ private:
|
|||
size_t bestIndex = left (index);
|
||||
|
||||
if (hasRight (index)) {
|
||||
size_t rightIndex = right (index);
|
||||
const size_t rightIndex = right (index);
|
||||
|
||||
if (m_data[rightIndex] < m_data[bestIndex]) {
|
||||
if (contents_[rightIndex] < contents_[bestIndex]) {
|
||||
bestIndex = rightIndex;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_data[index] > m_data[bestIndex]) {
|
||||
cr::swap (m_data[index], m_data[bestIndex]);
|
||||
if (contents_[index] > contents_[bestIndex]) {
|
||||
cr::swap (contents_[index], contents_[bestIndex]);
|
||||
|
||||
index = bestIndex;
|
||||
bestIndex = left (index);
|
||||
|
|
@ -122,7 +129,7 @@ private:
|
|||
private:
|
||||
BinaryHeap &operator = (BinaryHeap &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
m_data = cr::move (rhs.m_data);
|
||||
contents_ = cr::move (rhs.contents_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -141,11 +148,11 @@ private:
|
|||
}
|
||||
|
||||
bool hasLeft (size_t index) const {
|
||||
return left (index) < m_data.length ();
|
||||
return left (index) < contents_.length ();
|
||||
}
|
||||
|
||||
bool hasRight (size_t index) const {
|
||||
return right (index) < m_data.length ();
|
||||
return right (index) < contents_.length ();
|
||||
}
|
||||
};
|
||||
|
||||
47
ext/crlib/cr-color.h
Normal file
47
ext/crlib/cr-color.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple color holder
|
||||
class Color final {
|
||||
public:
|
||||
int32 red = 0, green = 0, blue = 0;
|
||||
|
||||
public:
|
||||
Color (int32 r, int32 g, int32 b) : red (r), green (g), blue (b) { }
|
||||
|
||||
explicit Color () = default;
|
||||
~Color () = default;
|
||||
|
||||
public:
|
||||
void reset () {
|
||||
red = green = blue = 0;
|
||||
}
|
||||
|
||||
int32 avg () const {
|
||||
return sum () / (sizeof (Color) / sizeof (int32));
|
||||
}
|
||||
|
||||
int32 sum () const {
|
||||
return red + green + blue;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -53,13 +60,27 @@ namespace detail {
|
|||
};
|
||||
|
||||
template <typename K, typename V> struct DictionaryBucket {
|
||||
uint32 hash = static_cast <size_t> (-1);
|
||||
K key = K ();
|
||||
V value = V ();
|
||||
uint32 hash = static_cast <uint32> (-1);
|
||||
K key {};
|
||||
V value {};
|
||||
|
||||
public:
|
||||
DictionaryBucket () = default;
|
||||
~DictionaryBucket () = default;
|
||||
|
||||
public:
|
||||
DictionaryBucket (DictionaryBucket &&rhs) noexcept : hash (rhs.hash), key (cr::move (rhs.key)), value (cr::move (rhs.value))
|
||||
{ }
|
||||
|
||||
public:
|
||||
DictionaryBucket &operator = (DictionaryBucket &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
key = cr::move (rhs.key);
|
||||
value = cr::move (rhs.value);
|
||||
hash = rhs.hash;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +97,7 @@ public:
|
|||
|
||||
private:
|
||||
Array <DictList *> m_table;
|
||||
Array <DictBucket> m_buckets;
|
||||
Array <DictBucket> m_buckets{};
|
||||
H m_hasher;
|
||||
|
||||
private:
|
||||
|
|
@ -84,7 +105,7 @@ private:
|
|||
return m_hasher (key);
|
||||
}
|
||||
|
||||
size_t findIndexOrAllocate (const K &key, bool allocate) {
|
||||
size_t find (const K &key, bool allocate) {
|
||||
auto hashed = hash (key);
|
||||
auto pos = hashed % m_table.length ();
|
||||
|
||||
|
|
@ -100,7 +121,7 @@ private:
|
|||
|
||||
auto allocated = alloc.allocate <DictList> ();
|
||||
|
||||
allocated->index = created;
|
||||
allocated->index = static_cast <int32> (created);
|
||||
allocated->next = m_table[pos];
|
||||
|
||||
m_table[pos] = allocated;
|
||||
|
|
@ -114,7 +135,7 @@ private:
|
|||
}
|
||||
|
||||
size_t findIndex (const K &key) const {
|
||||
return const_cast <Dictionary *> (this)->findIndexOrAllocate (key, false);
|
||||
return const_cast <Dictionary *> (this)->find (key, false);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -211,7 +232,7 @@ public:
|
|||
|
||||
public:
|
||||
V &operator [] (const K &key) {
|
||||
return m_buckets[findIndexOrAllocate (key, true)].value;
|
||||
return m_buckets[find (key, true)].value;
|
||||
}
|
||||
|
||||
const V &operator [] (const K &key) const {
|
||||
393
ext/crlib/cr-files.h
Normal file
393
ext/crlib/cr-files.h
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-string.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple stdio file wrapper
|
||||
class File final : private DenyCopying {
|
||||
private:
|
||||
FILE *handle_ = nullptr;
|
||||
size_t length_ {};
|
||||
|
||||
public:
|
||||
explicit File () = default;
|
||||
|
||||
File (StringRef file, StringRef mode = "rt") {
|
||||
open (file, mode);
|
||||
}
|
||||
|
||||
~File () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (StringRef file, StringRef mode) {
|
||||
if (!openFile (file, mode)) {
|
||||
return false;
|
||||
}
|
||||
fseek (handle_, 0L, SEEK_END);
|
||||
length_ = ftell (handle_);
|
||||
fseek (handle_, 0L, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
if (handle_ != nullptr) {
|
||||
fclose (handle_);
|
||||
handle_ = nullptr;
|
||||
}
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return !!feof (handle_);
|
||||
}
|
||||
|
||||
bool flush () const {
|
||||
return !!fflush (handle_);
|
||||
}
|
||||
|
||||
int get () const {
|
||||
return fgetc (handle_);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, int count) const {
|
||||
return fgets (buffer, count, handle_);
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
int ch = 0;
|
||||
SmallArray <char> data (255);
|
||||
|
||||
while ((ch = get ()) != EOF && !eof ()) {
|
||||
data.push (static_cast <char> (ch));
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
line.assign (data.data (), data.length ());
|
||||
|
||||
return !eof ();
|
||||
}
|
||||
|
||||
template <typename ...Args> size_t puts (const char *fmt, Args &&...args) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return fputs (strings.format (fmt, cr::forward <Args> (args)...), handle_);
|
||||
}
|
||||
|
||||
bool puts (const char *buffer) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
if (fputs (buffer, handle_) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int putChar (int ch) {
|
||||
return fputc (ch, handle_);
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
return fread (buffer, size, count, handle_);
|
||||
}
|
||||
|
||||
size_t write (void *buffer, size_t size, size_t count = 1) {
|
||||
return fwrite (buffer, size, count, handle_);
|
||||
}
|
||||
|
||||
bool seek (long offset, int origin) {
|
||||
if (fseek (handle_, offset, origin) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
::rewind (handle_);
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline bool exists (StringRef file) {
|
||||
File fp;
|
||||
|
||||
if (fp.open (file, "rb")) {
|
||||
fp.close ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void createPath (const char *path) {
|
||||
for (auto str = const_cast <char *> (path) + 1; *str; ++str) {
|
||||
if (*str == '/') {
|
||||
*str = 0;
|
||||
plat.createDirectory (path);
|
||||
*str = '/';
|
||||
}
|
||||
}
|
||||
plat.createDirectory (path);
|
||||
}
|
||||
|
||||
private:
|
||||
bool openFile (StringRef filename, StringRef mode) {
|
||||
if (*this) {
|
||||
close ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
fopen_s (&handle_, filename.chars (), mode.chars ());
|
||||
#else
|
||||
handle_ = fopen (filename.chars (), mode.chars ());
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// wrapper for memory file for loading data into the memory
|
||||
class MemFileStorage : public Singleton <MemFileStorage> {
|
||||
private:
|
||||
using LoadFunction = Lambda <uint8 * (const char *, int *)>;
|
||||
using FreeFunction = Lambda <void (void *)>;
|
||||
|
||||
private:
|
||||
LoadFunction loadFun_ = nullptr;
|
||||
FreeFunction freeFun_ = nullptr;
|
||||
|
||||
public:
|
||||
inline MemFileStorage () = default;
|
||||
inline ~MemFileStorage () = default;
|
||||
|
||||
public:
|
||||
void initizalize (LoadFunction loader, FreeFunction unloader) {
|
||||
loadFun_ = cr::move (loader);
|
||||
freeFun_ = cr::move (unloader);
|
||||
}
|
||||
|
||||
public:
|
||||
uint8 *load (StringRef file, int *size) {
|
||||
if (loadFun_) {
|
||||
return loadFun_ (file.chars (), size);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void unload (void *buffer) {
|
||||
if (freeFun_) {
|
||||
freeFun_ (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static uint8 *defaultLoad (const char *path, int *size) {
|
||||
File file (path, "rb");
|
||||
|
||||
if (!file) {
|
||||
*size = 0;
|
||||
return nullptr;
|
||||
}
|
||||
*size = static_cast <int> (file.length ());
|
||||
auto data = alloc.allocate <uint8> (*size);
|
||||
|
||||
file.read (data, *size);
|
||||
return data;
|
||||
}
|
||||
|
||||
static void defaultUnload (void *buffer) {
|
||||
alloc.deallocate (buffer);
|
||||
}
|
||||
|
||||
static String loadToString (StringRef filename) {
|
||||
int32 result = 0;
|
||||
auto buffer = defaultLoad (filename.chars (), &result);
|
||||
|
||||
if (result > 0 && buffer) {
|
||||
String data (reinterpret_cast <char *> (buffer), result);
|
||||
defaultUnload (buffer);
|
||||
|
||||
return data;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
class MemFile final : public DenyCopying {
|
||||
private:
|
||||
enum : char {
|
||||
Eof = static_cast <char> (-1)
|
||||
};
|
||||
|
||||
private:
|
||||
uint8 *contents_ = nullptr;
|
||||
size_t length_ {};
|
||||
size_t seek_ {};
|
||||
|
||||
public:
|
||||
explicit MemFile () = default;
|
||||
|
||||
MemFile (StringRef file) {
|
||||
open (file);
|
||||
}
|
||||
|
||||
~MemFile () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (StringRef file) {
|
||||
length_ = 0;
|
||||
seek_ = 0;
|
||||
contents_ = MemFileStorage::instance ().load (file.chars (), reinterpret_cast <int *> (&length_));
|
||||
|
||||
if (!contents_) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
MemFileStorage::instance ().unload (contents_);
|
||||
|
||||
length_ = 0;
|
||||
seek_ = 0;
|
||||
contents_ = nullptr;
|
||||
}
|
||||
|
||||
char get () {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return Eof;
|
||||
}
|
||||
auto ch = contents_[seek_];
|
||||
++seek_;
|
||||
|
||||
return static_cast <char> (ch);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, size_t count) {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t index = 0;
|
||||
buffer[0] = 0;
|
||||
|
||||
for (; index < count - 1;) {
|
||||
if (seek_ < length_) {
|
||||
buffer[index] = contents_[seek_++];
|
||||
|
||||
if (buffer[index++] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[index] = 0;
|
||||
return index ? buffer : nullptr;
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
char ch;
|
||||
SmallArray <char> data (255);
|
||||
|
||||
while ((ch = get ()) != Eof) {
|
||||
data.push (ch);
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
line.assign (data.data (), data.length ());
|
||||
|
||||
return !eof ();
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
if (!contents_ || length_ <= seek_ || !buffer || !size || !count) {
|
||||
return 0;
|
||||
}
|
||||
size_t blocksRead = size * count <= length_ - seek_ ? size * count : length_ - seek_;
|
||||
|
||||
memcpy (buffer, &contents_[seek_], blocksRead);
|
||||
seek_ += blocksRead;
|
||||
|
||||
return blocksRead / size;
|
||||
}
|
||||
|
||||
bool seek (size_t offset, int origin) {
|
||||
if (!contents_ || seek_ >= length_) {
|
||||
return false;
|
||||
}
|
||||
if (origin == SEEK_SET) {
|
||||
if (offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ = offset;
|
||||
}
|
||||
else if (origin == SEEK_END) {
|
||||
if (offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ = length_ - offset;
|
||||
}
|
||||
else {
|
||||
if (seek_ + offset >= length_) {
|
||||
return false;
|
||||
}
|
||||
seek_ += offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return seek_ >= length_;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
seek_ = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return !!contents_ && length_ > 0;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
170
ext/crlib/cr-hook.h
Normal file
170
ext/crlib/cr-hook.h
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
class SimpleHook : DenyCopying {
|
||||
private:
|
||||
#if defined (CR_ARCH_X64)
|
||||
using uint = uint64;
|
||||
#else
|
||||
using uint = uint32;
|
||||
#endif
|
||||
|
||||
private:
|
||||
enum : uint32 {
|
||||
#if defined (CR_ARCH_X64)
|
||||
CodeLength = 5 + sizeof (uint)
|
||||
#else
|
||||
CodeLength = 1 + sizeof (uint)
|
||||
#endif
|
||||
};
|
||||
|
||||
private:
|
||||
bool patched_;
|
||||
|
||||
uint pageSize_;
|
||||
uint originalFun_;
|
||||
uint hookedFun_;
|
||||
|
||||
UniquePtr <uint8 []> originalBytes_;
|
||||
UniquePtr <uint8 []> hookedBytes_;
|
||||
|
||||
private:
|
||||
void setPageSize () {
|
||||
#if defined (CR_WINDOWS)
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo (&sysinfo);
|
||||
|
||||
pageSize_ = sysinfo.dwPageSize;
|
||||
#else
|
||||
pageSize_ = sysconf (_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
void *align (void *address) {
|
||||
return reinterpret_cast <void *> ((reinterpret_cast <long> (address) & ~(pageSize_ - 1)));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool unprotect () {
|
||||
auto orig = reinterpret_cast <void *> (originalFun_);
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
DWORD oldProt;
|
||||
|
||||
FlushInstructionCache (GetCurrentProcess (), orig, CodeLength);
|
||||
return VirtualProtect (orig, CodeLength, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
#else
|
||||
auto aligned = align (orig);
|
||||
return !mprotect (aligned, pageSize_, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
SimpleHook () : patched_ (false), pageSize_ (0), originalFun_ (0), hookedFun_ (0) {
|
||||
setPageSize ();
|
||||
|
||||
originalBytes_ = makeUnique <uint8 []> (CodeLength);
|
||||
hookedBytes_ = makeUnique <uint8 []> (CodeLength);
|
||||
}
|
||||
|
||||
~SimpleHook () {
|
||||
disable ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool patch (void *address, void *replacement) {
|
||||
constexpr uint16 jmp = 0x25ff;
|
||||
|
||||
if (plat.arm) {
|
||||
return false;
|
||||
}
|
||||
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == jmp) {
|
||||
ptr = **reinterpret_cast <uint8 ***> (ptr + 2);
|
||||
}
|
||||
originalFun_ = reinterpret_cast <uint> (ptr);
|
||||
hookedFun_ = reinterpret_cast <uint> (replacement);
|
||||
|
||||
memcpy (originalBytes_.get (), reinterpret_cast <void *> (originalFun_), CodeLength);
|
||||
|
||||
if (plat.x64) {
|
||||
const uint16 nop = 0x00000000;
|
||||
|
||||
memcpy (&hookedBytes_[0], &jmp, sizeof (uint16));
|
||||
memcpy (&hookedBytes_[2], &nop, sizeof (uint16));
|
||||
memcpy (&hookedBytes_[6], &replacement, sizeof (uint));
|
||||
}
|
||||
else {
|
||||
hookedBytes_[0] = 0xe9;
|
||||
|
||||
auto rel = hookedFun_ - originalFun_ - CodeLength;
|
||||
memcpy (&hookedBytes_[0] + 1, &rel, sizeof (rel));
|
||||
}
|
||||
return enable ();
|
||||
}
|
||||
|
||||
bool enable () {
|
||||
if (patched_) {
|
||||
return false;
|
||||
}
|
||||
patched_ = true;
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (reinterpret_cast <void *> (originalFun_), hookedBytes_.get (), CodeLength);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool disable () {
|
||||
if (!patched_) {
|
||||
return false;
|
||||
}
|
||||
patched_ = false;
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (reinterpret_cast <void *> (originalFun_), originalBytes_.get (), CodeLength);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enabled () const {
|
||||
return patched_;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename... Args > decltype (auto) call (Args &&...args) {
|
||||
disable ();
|
||||
auto res = reinterpret_cast <T *> (originalFun_) (args...);
|
||||
enable ();
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -47,11 +54,11 @@ CR_NAMESPACE_BEGIN
|
|||
|
||||
class Socket final : public DenyCopying {
|
||||
private:
|
||||
int32 m_socket;
|
||||
uint32 m_timeout;
|
||||
int32 socket_;
|
||||
uint32 timeout_;
|
||||
|
||||
public:
|
||||
Socket () : m_socket (-1), m_timeout (2) {
|
||||
Socket () : socket_ (-1), timeout_ (2) {
|
||||
#if defined(CR_WINDOWS)
|
||||
WSADATA wsa;
|
||||
|
||||
|
|
@ -70,43 +77,45 @@ public:
|
|||
|
||||
|
||||
public:
|
||||
bool connect (const String &hostname) {
|
||||
bool connect (StringRef hostname) {
|
||||
addrinfo hints, *result = nullptr;
|
||||
plat.bzero (&hints, sizeof (hints));
|
||||
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
constexpr auto NumericServ = 0x00000008;
|
||||
|
||||
hints.ai_flags = NumericServ;
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if (getaddrinfo (hostname.chars (), "80", &hints, &result) != 0) {
|
||||
return false;
|
||||
}
|
||||
m_socket = static_cast <int> (socket (result->ai_family, result->ai_socktype, 0));
|
||||
socket_ = static_cast <int> (socket (result->ai_family, result->ai_socktype, 0));
|
||||
|
||||
if (m_socket < 0) {
|
||||
if (socket_ < 0) {
|
||||
freeaddrinfo (result);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getTimeouts = [&] () -> Twin <char *, size_t> {
|
||||
auto getTimeouts = [&] () -> Twin <char *, int32> {
|
||||
#if defined (CR_WINDOWS)
|
||||
DWORD tv = m_timeout * 1000;
|
||||
DWORD tv = timeout_ * 1000;
|
||||
#else
|
||||
timeval tv { static_cast <time_t> (m_timeout), 0 };
|
||||
timeval tv { static_cast <time_t> (timeout_), 0 };
|
||||
#endif
|
||||
return { reinterpret_cast <char *> (&tv), sizeof (tv) };
|
||||
return { reinterpret_cast <char *> (&tv), static_cast <int32> (sizeof (tv)) };
|
||||
};
|
||||
auto timeouts = getTimeouts ();
|
||||
|
||||
if (setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
if (setsockopt (socket_, SOL_SOCKET, SO_RCVTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
logger.message ("Unable to set SO_RCVTIMEO.");
|
||||
}
|
||||
|
||||
if (setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
if (setsockopt (socket_, SOL_SOCKET, SO_SNDTIMEO, timeouts.first, timeouts.second) == -1) {
|
||||
logger.message ("Unable to set SO_SNDTIMEO.");
|
||||
}
|
||||
|
||||
if (::connect (m_socket, result->ai_addr, static_cast <decltype (result->ai_addrlen)> (result->ai_addrlen)) == -1) {
|
||||
if (::connect (socket_, result->ai_addr, static_cast <int32> (result->ai_addrlen)) == -1) {
|
||||
disconnect ();
|
||||
freeaddrinfo (result);
|
||||
|
||||
|
|
@ -118,33 +127,33 @@ public:
|
|||
}
|
||||
|
||||
void setTimeout (uint32 timeout) {
|
||||
m_timeout = timeout;
|
||||
timeout_ = timeout;
|
||||
}
|
||||
|
||||
void disconnect () {
|
||||
#if defined(CR_WINDOWS)
|
||||
if (m_socket != -1) {
|
||||
closesocket (m_socket);
|
||||
if (socket_ != -1) {
|
||||
closesocket (socket_);
|
||||
}
|
||||
#else
|
||||
if (m_socket != -1)
|
||||
close (m_socket);
|
||||
if (socket_ != -1)
|
||||
close (socket_);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename U> int32 send (const U *buffer, int32 length) const {
|
||||
return ::send (m_socket, reinterpret_cast <const char *> (buffer), length, 0);
|
||||
return ::send (socket_, reinterpret_cast <const char *> (buffer), length, 0);
|
||||
}
|
||||
|
||||
template <typename U> int32 recv (U *buffer, int32 length) {
|
||||
return ::recv (m_socket, reinterpret_cast <char *> (buffer), length, 0);
|
||||
return ::recv (socket_, reinterpret_cast <char *> (buffer), length, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
static int32 CR_STDCALL sendto (int socket, const void *message, size_t length, int flags, const struct sockaddr *dest, int32 destLength) {
|
||||
#if defined (CR_WINDOWS)
|
||||
WSABUF buffer = { length, const_cast <char *> (reinterpret_cast <const char *> (message)) };
|
||||
WSABUF buffer = { static_cast <ULONG> (length), const_cast <char *> (reinterpret_cast <const char *> (message)) };
|
||||
DWORD sendLength = 0;
|
||||
|
||||
if (WSASendTo (socket, &buffer, 1, &sendLength, flags, dest, destLength, NULL, NULL) == SOCKET_ERROR) {
|
||||
|
|
@ -173,7 +182,7 @@ namespace detail {
|
|||
String path, protocol, host;
|
||||
|
||||
public:
|
||||
static HttpUri parse (const String &uri) {
|
||||
static HttpUri parse (StringRef uri) {
|
||||
HttpUri result;
|
||||
|
||||
if (uri.empty ()) {
|
||||
|
|
@ -184,11 +193,11 @@ namespace detail {
|
|||
if (protocol != String::InvalidIndex) {
|
||||
result.protocol = uri.substr (0, protocol);
|
||||
|
||||
size_t host = uri.find ("/", protocol + 3);
|
||||
size_t hostIndex = uri.find ("/", protocol + 3);
|
||||
|
||||
if (host != String::InvalidIndex) {
|
||||
result.path = uri.substr (host + 1);
|
||||
result.host = uri.substr (protocol + 3, host - protocol - 3);
|
||||
if (hostIndex != String::InvalidIndex) {
|
||||
result.path = uri.substr (hostIndex + 1);
|
||||
result.host = uri.substr (protocol + 3, hostIndex - protocol - 3);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -206,10 +215,10 @@ private:
|
|||
};
|
||||
|
||||
private:
|
||||
Socket m_socket;
|
||||
String m_userAgent = "crlib";
|
||||
HttpClientResult m_code = HttpClientResult::Undefined;
|
||||
int32 m_chunkSize = 4096;
|
||||
Socket socket_;
|
||||
String userAgent_ = "crlib";
|
||||
HttpClientResult statusCode_ = HttpClientResult::Undefined;
|
||||
int32 chunkSize_ = 4096;
|
||||
|
||||
public:
|
||||
HttpClient () = default;
|
||||
|
|
@ -221,8 +230,8 @@ private:
|
|||
int32 pos = 0, symbols = 0, errors = 0;
|
||||
|
||||
// prase response header
|
||||
while (!isFinished && pos < m_chunkSize) {
|
||||
if (m_socket.recv (&buffer[pos], 1) < 1) {
|
||||
while (!isFinished && pos < chunkSize_) {
|
||||
if (socket_.recv (&buffer[pos], 1) < 1) {
|
||||
if (++errors > MaxReceiveErrors) {
|
||||
isFinished = true;
|
||||
}
|
||||
|
|
@ -246,11 +255,12 @@ private:
|
|||
}
|
||||
++pos;
|
||||
}
|
||||
String response (reinterpret_cast <const char *> (buffer));
|
||||
String response { reinterpret_cast <const char *> (buffer) };
|
||||
size_t responseCodeStart = response.find ("HTTP/1.1");
|
||||
|
||||
if (responseCodeStart != String::InvalidIndex) {
|
||||
String respCode = response.substr (responseCodeStart + 9, 3).trim ();
|
||||
String respCode = response.substr (responseCodeStart + 9, 3);
|
||||
respCode.trim ();
|
||||
|
||||
if (respCode == "200") {
|
||||
return HttpClientResult::OK;
|
||||
|
|
@ -268,46 +278,46 @@ private:
|
|||
public:
|
||||
|
||||
// simple blocked download
|
||||
bool downloadFile (const String &url, const String &localPath) {
|
||||
bool downloadFile (StringRef url, StringRef localPath) {
|
||||
if (File::exists (localPath.chars ())) {
|
||||
m_code = HttpClientResult::LocalFileExists;
|
||||
statusCode_ = HttpClientResult::LocalFileExists;
|
||||
return false;
|
||||
}
|
||||
auto uri = detail::HttpUri::parse (url);
|
||||
|
||||
// no https...
|
||||
if (uri.protocol == "https") {
|
||||
m_code = HttpClientResult::HttpOnly;
|
||||
statusCode_ = HttpClientResult::HttpOnly;
|
||||
return false;
|
||||
}
|
||||
|
||||
// unable to connect...
|
||||
if (!m_socket.connect (uri.host)) {
|
||||
m_code = HttpClientResult::ConnectError;
|
||||
m_socket.disconnect ();
|
||||
if (!socket_.connect (uri.host)) {
|
||||
statusCode_ = HttpClientResult::ConnectError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
String request;
|
||||
request.appendf ("GET /%s HTTP/1.1\r\n", uri.path.chars ());
|
||||
request.appendf ("GET /%s HTTP/1.1\r\n", uri.path);
|
||||
request.append ("Accept: */*\r\n");
|
||||
request.append ("Connection: close\r\n");
|
||||
request.append ("Keep-Alive: 115\r\n");
|
||||
request.appendf ("User-Agent: %s\r\n", m_userAgent.chars ());
|
||||
request.appendf ("Host: %s\r\n\r\n", uri.host.chars ());
|
||||
request.appendf ("User-Agent: %s\r\n", userAgent_);
|
||||
request.appendf ("Host: %s\r\n\r\n", uri.host);
|
||||
|
||||
if (m_socket.send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
m_code = HttpClientResult::SocketError;
|
||||
m_socket.disconnect ();
|
||||
if (socket_.send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
SmallArray <uint8> buffer (m_chunkSize);
|
||||
m_code = parseResponseHeader (buffer.data ());
|
||||
SmallArray <uint8> buffer (chunkSize_);
|
||||
statusCode_ = parseResponseHeader (buffer.data ());
|
||||
|
||||
if (m_code != HttpClientResult::OK) {
|
||||
m_socket.disconnect ();
|
||||
if (statusCode_ != HttpClientResult::OK) {
|
||||
socket_.disconnect ();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -315,8 +325,8 @@ public:
|
|||
File file (localPath, "wb");
|
||||
|
||||
if (!file) {
|
||||
m_code = HttpClientResult::Undefined;
|
||||
m_socket.disconnect ();
|
||||
statusCode_ = HttpClientResult::Undefined;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -324,7 +334,7 @@ public:
|
|||
int32 errors = 0;
|
||||
|
||||
for (;;) {
|
||||
length = m_socket.recv (buffer.data (), m_chunkSize);
|
||||
length = socket_.recv (buffer.data (), chunkSize_);
|
||||
|
||||
if (length > 0) {
|
||||
file.write (buffer.data (), length);
|
||||
|
|
@ -335,29 +345,29 @@ public:
|
|||
}
|
||||
file.close ();
|
||||
|
||||
m_socket.disconnect ();
|
||||
m_code = HttpClientResult::OK;
|
||||
socket_.disconnect ();
|
||||
statusCode_ = HttpClientResult::OK;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool uploadFile (const String &url, const String &localPath) {
|
||||
bool uploadFile (StringRef url, StringRef localPath) {
|
||||
if (!File::exists (localPath.chars ())) {
|
||||
m_code = HttpClientResult::NoLocalFile;
|
||||
statusCode_ = HttpClientResult::NoLocalFile;
|
||||
return false;
|
||||
}
|
||||
auto uri = detail::HttpUri::parse (url);
|
||||
|
||||
// no https...
|
||||
if (uri.protocol == "https") {
|
||||
m_code = HttpClientResult::HttpOnly;
|
||||
statusCode_ = HttpClientResult::HttpOnly;
|
||||
return false;
|
||||
}
|
||||
|
||||
// unable to connect...
|
||||
if (!m_socket.connect (uri.host)) {
|
||||
m_code = HttpClientResult::ConnectError;
|
||||
m_socket.disconnect ();
|
||||
if (!socket_.connect (uri.host)) {
|
||||
statusCode_ = HttpClientResult::ConnectError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -366,8 +376,8 @@ public:
|
|||
File file (localPath, "rb");
|
||||
|
||||
if (!file) {
|
||||
m_code = HttpClientResult::Undefined;
|
||||
m_socket.disconnect ();
|
||||
statusCode_ = HttpClientResult::Undefined;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -377,44 +387,44 @@ public:
|
|||
if (boundarySlash != String::InvalidIndex) {
|
||||
boundaryName = localPath.substr (boundarySlash + 1);
|
||||
}
|
||||
const String &boundaryLine = "---crlib_upload_boundary_1337";
|
||||
StringRef boundaryLine = "---crlib_upload_boundary_1337";
|
||||
|
||||
String request, start, end;
|
||||
start.appendf ("--%s\r\n", boundaryLine.chars ());
|
||||
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName.chars ());
|
||||
start.appendf ("--%s\r\n", boundaryLine);
|
||||
start.appendf ("Content-Disposition: form-data; name='file'; filename='%s'\r\n", boundaryName);
|
||||
start.append ("Content-Type: application/octet-stream\r\n\r\n");
|
||||
|
||||
end.appendf ("\r\n--%s--\r\n\r\n", boundaryLine.chars ());
|
||||
end.appendf ("\r\n--%s--\r\n\r\n", boundaryLine);
|
||||
|
||||
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path.chars ());
|
||||
request.appendf ("Host: %s\r\n", uri.host.chars ());
|
||||
request.appendf ("User-Agent: %s\r\n", m_userAgent.chars ());
|
||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", boundaryLine.chars ());
|
||||
request.appendf ("POST /%s HTTP/1.1\r\n", uri.path);
|
||||
request.appendf ("Host: %s\r\n", uri.host);
|
||||
request.appendf ("User-Agent: %s\r\n", userAgent_);
|
||||
request.appendf ("Content-Type: multipart/form-data; boundary=%s\r\n", boundaryLine);
|
||||
request.appendf ("Content-Length: %d\r\n\r\n", file.length () + start.length () + end.length ());
|
||||
|
||||
// send the main request
|
||||
if (m_socket.send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
m_code = HttpClientResult::SocketError;
|
||||
m_socket.disconnect ();
|
||||
if (socket_.send (request.chars (), static_cast <int32> (request.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// send boundary start
|
||||
if (m_socket.send (start.chars (), static_cast <int32> (start.length ())) < 1) {
|
||||
m_code = HttpClientResult::SocketError;
|
||||
m_socket.disconnect ();
|
||||
if (socket_.send (start.chars (), static_cast <int32> (start.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
SmallArray <uint8> buffer (m_chunkSize);
|
||||
SmallArray <uint8> buffer (chunkSize_);
|
||||
int32 length = 0;
|
||||
|
||||
for (;;) {
|
||||
length = static_cast <int32> (file.read (buffer.data (), 1, m_chunkSize));
|
||||
length = static_cast <int32> (file.read (buffer.data (), 1, chunkSize_));
|
||||
|
||||
if (length > 0) {
|
||||
m_socket.send (buffer.data (), length);
|
||||
socket_.send (buffer.data (), length);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
|
|
@ -422,33 +432,33 @@ public:
|
|||
}
|
||||
|
||||
// send boundary end
|
||||
if (m_socket.send (end.chars (), static_cast <int32> (end.length ())) < 1) {
|
||||
m_code = HttpClientResult::SocketError;
|
||||
m_socket.disconnect ();
|
||||
if (socket_.send (end.chars (), static_cast <int32> (end.length ())) < 1) {
|
||||
statusCode_ = HttpClientResult::SocketError;
|
||||
socket_.disconnect ();
|
||||
|
||||
return false;
|
||||
}
|
||||
m_code = parseResponseHeader (buffer.data ());
|
||||
m_socket.disconnect ();
|
||||
statusCode_ = parseResponseHeader (buffer.data ());
|
||||
socket_.disconnect ();
|
||||
|
||||
return m_code == HttpClientResult::OK;
|
||||
return statusCode_ == HttpClientResult::OK;
|
||||
}
|
||||
|
||||
public:
|
||||
void setUserAgent (const String &ua) {
|
||||
m_userAgent = ua;
|
||||
void setUserAgent (StringRef ua) {
|
||||
userAgent_ = ua;
|
||||
}
|
||||
|
||||
HttpClientResult getLastStatusCode () {
|
||||
return m_code;
|
||||
return statusCode_;
|
||||
}
|
||||
|
||||
void setChunkSize (int32 chunkSize) {
|
||||
m_chunkSize = chunkSize;
|
||||
chunkSize_ = chunkSize;
|
||||
}
|
||||
|
||||
void setTimeout (uint32 timeout) {
|
||||
m_socket.setTimeout (timeout);
|
||||
socket_.setTimeout (timeout);
|
||||
}
|
||||
};
|
||||
|
||||
182
ext/crlib/cr-lambda.h
Normal file
182
ext/crlib/cr-lambda.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename> class Lambda;
|
||||
template <typename R, typename ...Args> class Lambda <R (Args...)> {
|
||||
private:
|
||||
enum : uint32 {
|
||||
LamdaSmallBufferLength = sizeof (void *) * 16
|
||||
};
|
||||
|
||||
private:
|
||||
class LambdaFunctorWrapper {
|
||||
public:
|
||||
LambdaFunctorWrapper () = default;
|
||||
virtual ~LambdaFunctorWrapper () = default;
|
||||
|
||||
public:
|
||||
virtual void move (uint8 *to) = 0;
|
||||
virtual void small (uint8 *to) const = 0;
|
||||
|
||||
virtual R invoke (Args &&...) = 0;
|
||||
virtual UniquePtr <LambdaFunctorWrapper> clone () const = 0;
|
||||
|
||||
public:
|
||||
void operator delete (void *ptr) {
|
||||
alloc.deallocate (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class LambdaFunctor : public LambdaFunctorWrapper {
|
||||
private:
|
||||
T callable_;
|
||||
|
||||
public:
|
||||
LambdaFunctor (const T &callable) : LambdaFunctorWrapper (), callable_ (callable)
|
||||
{ }
|
||||
|
||||
LambdaFunctor (T &&callable) : LambdaFunctorWrapper (), callable_ (cr::move (callable))
|
||||
{ }
|
||||
|
||||
~LambdaFunctor () override = default;
|
||||
|
||||
public:
|
||||
void move (uint8 *to) override {
|
||||
new (to) LambdaFunctor <T> (cr::move (callable_));
|
||||
}
|
||||
|
||||
void small (uint8 *to) const override {
|
||||
new (to) LambdaFunctor <T> (callable_);
|
||||
}
|
||||
|
||||
R invoke (Args &&... args) override {
|
||||
return callable_ (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||
return makeUnique <LambdaFunctor <T>> (callable_);
|
||||
}
|
||||
};
|
||||
|
||||
union {
|
||||
UniquePtr <LambdaFunctorWrapper> functor_;
|
||||
uint8 small_[LamdaSmallBufferLength];
|
||||
};
|
||||
|
||||
bool ssoObject_ = false;
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
if (ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (small_)->~LambdaFunctorWrapper ();
|
||||
}
|
||||
else {
|
||||
functor_.reset ();
|
||||
}
|
||||
}
|
||||
|
||||
void swap (Lambda &rhs) noexcept {
|
||||
cr::swap (rhs, *this);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Lambda () noexcept : Lambda (nullptr)
|
||||
{ }
|
||||
|
||||
Lambda (decltype (nullptr)) noexcept : functor_ (nullptr), ssoObject_ (false)
|
||||
{ }
|
||||
|
||||
Lambda (const Lambda &rhs) {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <const LambdaFunctorWrapper *> (rhs.small_)->small (small_);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (rhs.functor_->clone ());
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
}
|
||||
|
||||
Lambda (Lambda &&rhs) noexcept {
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
}
|
||||
|
||||
template <typename F> Lambda (F function) {
|
||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||
ssoObject_ = false;
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||
}
|
||||
else {
|
||||
ssoObject_ = true;
|
||||
new (small_) LambdaFunctor <F> (cr::move (function));
|
||||
}
|
||||
}
|
||||
|
||||
~Lambda () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
Lambda &operator = (const Lambda &rhs) {
|
||||
destroy ();
|
||||
|
||||
Lambda tmp (rhs);
|
||||
swap (tmp);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Lambda &operator = (Lambda &&rhs) noexcept {
|
||||
destroy ();
|
||||
|
||||
if (rhs.ssoObject_) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.small_)->move (small_);
|
||||
new (rhs.small_) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (small_) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.functor_));
|
||||
}
|
||||
|
||||
ssoObject_ = rhs.ssoObject_;
|
||||
rhs.ssoObject_ = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool () const noexcept {
|
||||
return ssoObject_ || !!functor_;
|
||||
}
|
||||
|
||||
public:
|
||||
R operator () (Args ...args) {
|
||||
return ssoObject_ ? reinterpret_cast <LambdaFunctorWrapper *> (small_)->invoke (cr::forward <Args> (args)...) : functor_->invoke (cr::forward <Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
130
ext/crlib/cr-library.h
Normal file
130
ext/crlib/cr-library.h
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-string.h>
|
||||
|
||||
#if defined (CR_LINUX) || defined (CR_OSX)
|
||||
# include <dlfcn.h>
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// handling dynamic library loading
|
||||
class SharedLibrary final : public DenyCopying {
|
||||
public:
|
||||
using Handle = void *;
|
||||
|
||||
private:
|
||||
Handle handle_ = nullptr;
|
||||
|
||||
public:
|
||||
explicit SharedLibrary () = default;
|
||||
|
||||
SharedLibrary (StringRef file) {
|
||||
if (file.empty ()) {
|
||||
return;
|
||||
}
|
||||
load (file);
|
||||
}
|
||||
|
||||
~SharedLibrary () {
|
||||
unload ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool load (StringRef file) noexcept {
|
||||
if (*this) {
|
||||
unload ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
handle_ = LoadLibraryA (file.chars ());
|
||||
#else
|
||||
handle_ = dlopen (file.chars (), RTLD_LAZY);
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
bool locate (Handle address) {
|
||||
#if defined (CR_WINDOWS)
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
if (!VirtualQuery (address, &mbi, sizeof (mbi))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mbi.State != MEM_COMMIT) {
|
||||
return false;
|
||||
}
|
||||
handle_ = reinterpret_cast <Handle> (mbi.AllocationBase);
|
||||
#else
|
||||
Dl_info dli;
|
||||
plat.bzero (&dli, sizeof (dli));
|
||||
|
||||
if (dladdr (address, &dli)) {
|
||||
return load (dli.dli_fname);
|
||||
}
|
||||
#endif
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
void unload () noexcept {
|
||||
if (!*this) {
|
||||
return;
|
||||
}
|
||||
#if defined (CR_WINDOWS)
|
||||
FreeLibrary (static_cast <HMODULE> (handle_));
|
||||
#else
|
||||
dlclose (handle_);
|
||||
#endif
|
||||
handle_ = nullptr;
|
||||
}
|
||||
|
||||
template <typename R> R resolve (const char *function) const {
|
||||
if (!*this) {
|
||||
return nullptr;
|
||||
}
|
||||
return SharedLibrary::getSymbol <R> (handle (), function);
|
||||
}
|
||||
|
||||
Handle handle () const {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename R> static inline R CR_STDCALL getSymbol (Handle module, const char *function) {
|
||||
return reinterpret_cast <R> (
|
||||
#if defined (CR_WINDOWS)
|
||||
GetProcAddress (static_cast <HMODULE> (module), function)
|
||||
#else
|
||||
dlsym (module, function)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -20,19 +27,19 @@ public:
|
|||
using PrintFunction = Lambda <void (const char *)>;
|
||||
|
||||
private:
|
||||
File m_handle;
|
||||
PrintFunction m_printer;
|
||||
File handle_;
|
||||
PrintFunction printFun_;
|
||||
|
||||
public:
|
||||
SimpleLogger () = default;
|
||||
|
||||
~SimpleLogger () {
|
||||
m_handle.close ();
|
||||
handle_.close ();
|
||||
}
|
||||
|
||||
private:
|
||||
void logToFile (const char *level, const char *msg) {
|
||||
if (!m_handle) {
|
||||
if (!handle_) {
|
||||
return;
|
||||
}
|
||||
time_t ticks = time (&ticks);
|
||||
|
|
@ -50,48 +57,48 @@ private:
|
|||
auto timebuf = strings.chars ();
|
||||
strftime (timebuf, StringBuffer::StaticBufferSize, "%Y-%m-%d %H:%M:%S", timeinfo);
|
||||
|
||||
m_handle.puts ("%s (%s): %s\n", timebuf, level, msg);
|
||||
handle_.puts ("%s (%s): %s\n", timebuf, level, msg);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename ...Args> void fatal (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void fatal (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("FATAL", msg);
|
||||
|
||||
if (m_printer) {
|
||||
m_printer (msg);
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
plat.abort (msg);
|
||||
}
|
||||
|
||||
template <typename ...Args> void error (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void error (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("ERROR", msg);
|
||||
|
||||
if (m_printer) {
|
||||
m_printer (msg);
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ...Args> void message (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void message (const char *fmt, Args &&...args) {
|
||||
auto msg = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
logToFile ("INFO", msg);
|
||||
|
||||
if (m_printer) {
|
||||
m_printer (msg);
|
||||
if (printFun_) {
|
||||
printFun_ (msg);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void initialize (const String &filename, PrintFunction printFunction) {
|
||||
if (m_handle) {
|
||||
m_handle.close ();
|
||||
void initialize (StringRef filename, PrintFunction printFunction) {
|
||||
if (handle_) {
|
||||
handle_.close ();
|
||||
}
|
||||
m_printer = cr::move (printFunction);
|
||||
m_handle.open (filename, "at");
|
||||
printFun_ = cr::move (printFunction);
|
||||
handle_.open (filename, "at");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1,19 +1,28 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
#if defined (CR_HAS_SSE2)
|
||||
# include <immintrin.h>
|
||||
#if defined (CR_HAS_SSE)
|
||||
# include <pmmintrin.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
constexpr float kFloatEpsilon = 0.01f;
|
||||
|
|
@ -21,8 +30,7 @@ constexpr float kFloatEqualEpsilon = 0.001f;
|
|||
constexpr float kFloatCmpEpsilon = 1.192092896e-07f;
|
||||
|
||||
constexpr float kMathPi = 3.141592653589793115997963468544185161590576171875f;
|
||||
constexpr float kMathPiReciprocal = 1.0f / kMathPi;
|
||||
constexpr float kMathPiHalf = kMathPi / 2;
|
||||
constexpr float kMathPiHalf = kMathPi * 0.5f;
|
||||
|
||||
constexpr float kDegreeToRadians = kMathPi / 180.0f;
|
||||
constexpr float kRadiansToDegree = 180.0f / kMathPi;
|
||||
|
|
@ -35,11 +43,11 @@ constexpr bool fequal (const float a, const float b) {
|
|||
return cr:: abs (a - b) < kFloatEqualEpsilon;
|
||||
}
|
||||
|
||||
constexpr float radiansToDegrees (const float r) {
|
||||
constexpr float rad2deg (const float r) {
|
||||
return r * kRadiansToDegree;
|
||||
}
|
||||
|
||||
constexpr float degreesToRadians (const float d) {
|
||||
constexpr float deg2rad (const float d) {
|
||||
return d * kDegreeToRadians;
|
||||
}
|
||||
|
||||
|
|
@ -56,82 +64,39 @@ constexpr float anglesDifference (const float a, const float b) {
|
|||
}
|
||||
|
||||
inline float sinf (const float value) {
|
||||
const auto sign = static_cast <int32> (value * kMathPiReciprocal);
|
||||
const float calc = (value - static_cast <float> (sign) * kMathPi);
|
||||
|
||||
const float sqr = cr::square (calc);
|
||||
const float res = 1.00000000000000000000e+00f + sqr * (-1.66666671633720397949e-01f + sqr * (8.33333376795053482056e-03f + sqr * (-1.98412497411482036114e-04f +
|
||||
sqr * (2.75565571428160183132e-06f + sqr * (-2.50368472620721149724e-08f + sqr * (1.58849267073435385100e-10f + sqr * -6.58925550841432672300e-13f))))));
|
||||
|
||||
return (sign & 1) ? -calc * res : value * res;
|
||||
return ::sinf (value);
|
||||
}
|
||||
|
||||
inline float cosf (const float value) {
|
||||
const auto sign = static_cast <int32> (value * kMathPiReciprocal);
|
||||
const float calc = (value - static_cast <float> (sign) * kMathPi);
|
||||
|
||||
const float sqr = cr::square (calc);
|
||||
const float res = sqr * (-5.00000000000000000000e-01f + sqr * (4.16666641831398010254e-02f + sqr * (-1.38888671062886714935e-03f + sqr * (2.48006890615215525031e-05f +
|
||||
sqr * (-2.75369927749125054106e-07f + sqr * (2.06207229069832465029e-09f + sqr * -9.77507137733812925262e-12f))))));
|
||||
|
||||
const float f = -1.00000000000000000000e+00f;
|
||||
|
||||
return (sign & 1) ? f - res : -f + res;
|
||||
return ::cosf (value);
|
||||
}
|
||||
|
||||
inline float atanf (const float x) {
|
||||
const float sqr = cr::square (x);
|
||||
return x * (48.70107004404898384f + sqr * (49.5326263772254345f + sqr * 9.40604244231624f)) / (48.70107004404996166f + sqr * (65.7663163908956299f + sqr * (21.587934067020262f + sqr)));
|
||||
inline float atanf (const float value) {
|
||||
return ::atanf (value);
|
||||
}
|
||||
|
||||
inline float atan2f (const float y, const float x) {
|
||||
const float ax = cr::abs (x);
|
||||
const float ay = cr::abs (y);
|
||||
|
||||
if (ax < 1e-7f && ay < 1e-7f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (ax > ay) {
|
||||
if (x < 0.0f) {
|
||||
if (y >= 0.0f) {
|
||||
return atanf (y / x) + kMathPi;
|
||||
}
|
||||
return atanf (y / x) - kMathPi;
|
||||
}
|
||||
return atanf (y / x);
|
||||
}
|
||||
|
||||
if (y < 0.0f) {
|
||||
return atanf (-x / y) - kMathPiHalf;
|
||||
}
|
||||
return atanf (-x / y) + kMathPiHalf;
|
||||
return ::atan2f (y, x);
|
||||
}
|
||||
|
||||
inline float powf (const float x, const float y) {
|
||||
union {
|
||||
float d;
|
||||
int x;
|
||||
} res { x };
|
||||
|
||||
res.x = static_cast <int> (y * (res.x - 1064866805) + 1064866805);
|
||||
return res.d;
|
||||
return ::powf (x, y);
|
||||
}
|
||||
|
||||
inline float sqrtf (const float value) {
|
||||
return powf (value, 0.5f);
|
||||
return ::sqrtf (value);
|
||||
}
|
||||
|
||||
inline float tanf (const float value) {
|
||||
return sinf (value) / cosf (value);
|
||||
return ::tanf (value);
|
||||
}
|
||||
|
||||
constexpr float ceilf (const float x) {
|
||||
return static_cast <float> (65536 - static_cast <int> (65536.0f - x));
|
||||
inline float ceilf (const float value) {
|
||||
return ::ceilf (value);
|
||||
}
|
||||
|
||||
inline void sincosf (const float x, const float y, const float z, float *sines, float *cosines) {
|
||||
#if defined (CR_HAS_SSE2)
|
||||
#if defined (CR_HAS_SSE)
|
||||
auto set = _mm_set_ps (x, y, z, 0.0f);
|
||||
|
||||
auto _mm_sin = [] (__m128 rad) -> __m128 {
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -28,9 +35,19 @@ CR_NAMESPACE_BEGIN
|
|||
|
||||
// detects the compiler
|
||||
#if defined(_MSC_VER)
|
||||
# define CR_CXX_MSVC
|
||||
#elif defined(__clang__)
|
||||
# define CR_CXX_CLANG
|
||||
# define CR_CXX_MSVC _MSC_VER
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# define CR_CXX_CLANG __clang__
|
||||
#endif
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
# define CR_CXX_INTEL __INTEL_COMPILER
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define CR_CXX_GCC __GNUC__
|
||||
#endif
|
||||
|
||||
// configure macroses
|
||||
|
|
@ -60,7 +77,24 @@ CR_NAMESPACE_BEGIN
|
|||
#endif
|
||||
|
||||
#if (defined(CR_ARCH_X86) || defined(CR_ARCH_X64)) && !defined(CR_DEBUG)
|
||||
# define CR_HAS_SSE2
|
||||
# define CR_HAS_SSE
|
||||
#endif
|
||||
|
||||
#if defined(CR_HAS_SSE)
|
||||
# if defined (CR_CXX_MSVC)
|
||||
# define CR_ALIGN16 __declspec (align (16))
|
||||
# else
|
||||
# define CR_ALIGN16 __attribute__((aligned(16)))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// disable warnings regarding intel compiler
|
||||
#if defined(CR_CXX_INTEL)
|
||||
# pragma warning (disable : 3280) // declaration hides member "XXX" (declared at line XX)
|
||||
# pragma warning (disable : 2415) // variable "XXX" of static storage duration was declared but never referenced
|
||||
# pragma warning (disable : 873) // function "operator new(size_t={unsigned int}, void *)" has no corresponding operator delete (to be called if an exception is thrown during initialization of an allocated object)
|
||||
# pragma warning (disable : 383) // value copied to temporary, reference to temporary used
|
||||
# pragma warning (disable : 11074 11075) // remarks about inlining bla-bla-bla
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -97,8 +131,6 @@ CR_NAMESPACE_END
|
|||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
class String;
|
||||
|
||||
// helper struct for platform detection
|
||||
struct Platform : public Singleton <Platform> {
|
||||
bool win32 = false;
|
||||
|
|
@ -230,7 +262,7 @@ struct Platform : public Singleton <Platform> {
|
|||
static char result[256];
|
||||
bzero (result, sizeof (result));
|
||||
|
||||
#if defined(CR_WINDOWS)
|
||||
#if defined(CR_WINDOWS) && !defined(CR_CXX_GCC)
|
||||
char *buffer = nullptr;
|
||||
size_t size = 0;
|
||||
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -16,17 +23,17 @@ CR_NAMESPACE_BEGIN
|
|||
// random number generator see: https://github.com/preshing/RandomSequence/
|
||||
class Random final : public Singleton <Random> {
|
||||
private:
|
||||
uint32 m_index, m_offset;
|
||||
uint64 m_divider;
|
||||
uint32 index_, offset_;
|
||||
uint64 divider_;
|
||||
|
||||
public:
|
||||
explicit Random () {
|
||||
const auto base = static_cast <uint32> (time (nullptr));
|
||||
const auto offset = base + 1;
|
||||
|
||||
m_index = premute (premute (base) + 0x682f0161);
|
||||
m_offset = premute (premute (offset) + 0x46790905);
|
||||
m_divider = (static_cast <uint64> (1)) << 32;
|
||||
index_ = premute (premute (base) + 0x682f0161);
|
||||
offset_ = premute (premute (offset) + 0x46790905);
|
||||
divider_ = (static_cast <uint64> (1)) << 32;
|
||||
}
|
||||
~Random () = default;
|
||||
|
||||
|
|
@ -42,16 +49,16 @@ private:
|
|||
}
|
||||
|
||||
uint32 generate () {
|
||||
return premute ((premute (m_index++) + m_offset) ^ 0x5bf03635);
|
||||
return premute ((premute (index_++) + offset_) ^ 0x5bf03635);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename U> U int_ (U low, U high) {
|
||||
return static_cast <U> (generate () * (static_cast <double> (high) - static_cast <double> (low) + 1.0) / m_divider + static_cast <double> (low));
|
||||
return static_cast <U> (generate () * (static_cast <double> (high) - static_cast <double> (low) + 1.0) / divider_ + static_cast <double> (low));
|
||||
}
|
||||
|
||||
float float_ (float low, float high) {
|
||||
return static_cast <float> (generate () * (static_cast <double> (high) - static_cast <double> (low)) / (m_divider - 1) + static_cast <double> (low));
|
||||
return static_cast <float> (generate () * (static_cast <double> (high) - static_cast <double> (low)) / (divider_ - 1) + static_cast <double> (low));
|
||||
}
|
||||
|
||||
template <typename U> bool chance (const U max, const U maxChance = 100) {
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -36,20 +43,20 @@ private:
|
|||
|
||||
|
||||
private:
|
||||
SmallArray <int32> m_hashTable;
|
||||
SmallArray <int32> m_prevTable;
|
||||
SmallArray <int32> hashTable_;
|
||||
SmallArray <int32> prevTable_;
|
||||
|
||||
public:
|
||||
explicit ULZ () {
|
||||
m_hashTable.resize (HashLength);
|
||||
m_prevTable.resize (WindowSize);
|
||||
hashTable_.resize (HashLength);
|
||||
prevTable_.resize (WindowSize);
|
||||
}
|
||||
|
||||
~ULZ () = default;
|
||||
|
||||
public:
|
||||
int32 compress (uint8 *in, int32 inputLength, uint8 *out) {
|
||||
for (auto &htb : m_hashTable) {
|
||||
for (auto &htb : hashTable_) {
|
||||
htb = EmptyHash;
|
||||
}
|
||||
auto op = out;
|
||||
|
|
@ -67,7 +74,7 @@ public:
|
|||
const int32 limit = cr::max <int32> (cur - WindowSize, EmptyHash);
|
||||
|
||||
int32 chainLength = MaxChain;
|
||||
int32 lookup = m_hashTable[hash32 (&in[cur])];
|
||||
int32 lookup = hashTable_[hash32 (&in[cur])];
|
||||
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[cur + bestLength] && load <uint32> (&in[lookup]) == load <uint32> (&in[cur])) {
|
||||
|
|
@ -90,7 +97,7 @@ public:
|
|||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = m_prevTable[lookup & WindowMask];
|
||||
lookup = prevTable_[lookup & WindowMask];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +111,7 @@ public:
|
|||
const auto limit = cr::max <int32> (next - WindowSize, EmptyHash);
|
||||
|
||||
int32 chainLength = MaxChain;
|
||||
int32 lookup = m_hashTable[hash32 (&in[next])];
|
||||
int32 lookup = hashTable_[hash32 (&in[next])];
|
||||
|
||||
while (lookup > limit) {
|
||||
if (in[lookup + bestLength] == in[next + bestLength] && load <uint32> (&in[lookup]) == load <uint32> (&in[next])) {
|
||||
|
|
@ -123,7 +130,7 @@ public:
|
|||
if (--chainLength == 0) {
|
||||
break;
|
||||
}
|
||||
lookup = m_prevTable[lookup & WindowMask];
|
||||
lookup = prevTable_[lookup & WindowMask];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,22 +158,22 @@ public:
|
|||
if (length >= 15) {
|
||||
encode (op, length - 15);
|
||||
}
|
||||
store16 (op, dist);
|
||||
store16 (op, static_cast <uint16> (dist));
|
||||
op += 2;
|
||||
|
||||
while (bestLength-- != 0) {
|
||||
const auto hash = hash32 (&in[cur]);
|
||||
|
||||
m_prevTable[cur & WindowMask] = m_hashTable[hash];
|
||||
m_hashTable[hash] = cur++;
|
||||
prevTable_[cur & WindowMask] = hashTable_[hash];
|
||||
hashTable_[hash] = cur++;
|
||||
}
|
||||
anchor = cur;
|
||||
}
|
||||
else {
|
||||
const auto hash = hash32 (&in[cur]);
|
||||
|
||||
m_prevTable[cur & WindowMask] = m_hashTable[hash];
|
||||
m_hashTable[hash] = cur++;
|
||||
prevTable_[cur & WindowMask] = hashTable_[hash];
|
||||
hashTable_[hash] = cur++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +190,7 @@ public:
|
|||
copy (op, &in[anchor], run);
|
||||
op += run;
|
||||
}
|
||||
return op - out;
|
||||
return static_cast <int32> (op - out);
|
||||
}
|
||||
|
||||
int32 uncompress (uint8 *in, int32 inputLength, uint8 *out, int32 outLength) {
|
||||
|
|
@ -258,7 +265,7 @@ private:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void store16 (void *ptr, int32 val) {
|
||||
void store16 (void *ptr, uint16 val) {
|
||||
memcpy (ptr, &val, sizeof (uint16));
|
||||
}
|
||||
|
||||
212
ext/crlib/cr-uniqueptr.h
Normal file
212
ext/crlib/cr-uniqueptr.h
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
//
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple unique ptr
|
||||
template <typename T> class UniquePtr final : public DenyCopying {
|
||||
private:
|
||||
T *ptr_ {};
|
||||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : ptr_ (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
T *get () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T *release () {
|
||||
auto ret = ptr_;
|
||||
ptr_ = nullptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset (T *ptr = nullptr) {
|
||||
destroy ();
|
||||
ptr_ = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
alloc.destroy (ptr_);
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr &operator = (decltype (nullptr)) {
|
||||
destroy ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator * () const {
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
T *operator -> () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class UniquePtr <T[]> final : public DenyCopying {
|
||||
private:
|
||||
T *ptr_ { };
|
||||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : ptr_ (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : ptr_ (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
T *get () const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
T *release () {
|
||||
auto ret = ptr_;
|
||||
ptr_ = nullptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset (T *ptr = nullptr) {
|
||||
destroy ();
|
||||
ptr_ = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
alloc.destroy (ptr_);
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr &operator = (decltype (nullptr)) {
|
||||
destroy ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator [] (size_t index) {
|
||||
return ptr_[index];
|
||||
}
|
||||
const T &operator [] (size_t index) const {
|
||||
return ptr_[index];
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return ptr_ != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct ClearExtent {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct ClearExtent <T[]> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T, size_t N> struct ClearExtent <T[N]> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct UniqueIf {
|
||||
using SingleObject = UniquePtr <T>;
|
||||
};
|
||||
|
||||
template <typename T> struct UniqueIf<T[]> {
|
||||
using UnknownBound = UniquePtr <T[]>;
|
||||
};
|
||||
|
||||
template <typename T, size_t N> struct UniqueIf <T[N]> {
|
||||
using KnownBound = void;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::SingleObject makeUnique (Args &&... args) {
|
||||
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
template <typename T> typename detail::UniqueIf <T>::UnknownBound makeUnique (size_t size) {
|
||||
return UniquePtr <T> (alloc.createArray <typename detail::ClearExtent <T>::Type> (size));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args> typename detail::UniqueIf <T>::KnownBound makeUnique (Args &&...) = delete;
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// CRLib - Simple library for STL replacement in private projects.
|
||||
// Copyright © 2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -12,10 +19,56 @@
|
|||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// small simd operations for 3d vector
|
||||
#if defined (CR_HAS_SSE)
|
||||
|
||||
template <typename T> class CR_ALIGN16 SimdWrap {
|
||||
private:
|
||||
__m128 wrap_dp_sse2 (__m128 v1, __m128 v2) {
|
||||
auto mul = _mm_mul_ps (v1, v2);
|
||||
auto res = _mm_add_ps (_mm_shuffle_ps (v2, mul, _MM_SHUFFLE (1, 0, 0, 0)), mul);
|
||||
|
||||
mul = _mm_add_ps (_mm_shuffle_ps (mul, res, _MM_SHUFFLE (0, 3, 0, 0)), res);
|
||||
|
||||
return _mm_shuffle_ps (mul, mul, _MM_SHUFFLE (2, 2, 2, 2));
|
||||
}
|
||||
|
||||
public:
|
||||
union {
|
||||
__m128 m;
|
||||
|
||||
struct {
|
||||
T x, y, z;
|
||||
} vec;
|
||||
};
|
||||
|
||||
SimdWrap (const T &x, const T &y, const T &z) {
|
||||
m = _mm_set_ps (0.0f, z, y, x);
|
||||
}
|
||||
|
||||
SimdWrap (const T &x, const T &y) {
|
||||
m = _mm_set_ps (0.0f, 0.0f, y, x);
|
||||
}
|
||||
|
||||
SimdWrap (__m128 m) : m (m)
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
public:
|
||||
SimdWrap normalize () {
|
||||
return { _mm_div_ps (m, _mm_sqrt_ps (wrap_dp_sse2 (m, m))) };
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// 3dmath vector
|
||||
template <typename T> class Vec3D {
|
||||
public:
|
||||
T x = 0.0f, y = 0.0f, z = 0.0f;
|
||||
T x {};
|
||||
T y {};
|
||||
T z {};
|
||||
|
||||
public:
|
||||
Vec3D (const T &scaler = 0.0f) : x (scaler), y (scaler), z (scaler)
|
||||
|
|
@ -27,6 +80,11 @@ public:
|
|||
Vec3D (T *rhs) : x (rhs[0]), y (rhs[1]), z (rhs[2])
|
||||
{ }
|
||||
|
||||
#if defined (CR_HAS_SSE)
|
||||
Vec3D (const SimdWrap <T> &rhs) : x (rhs.vec.x), y (rhs.vec.y), z (rhs.vec.z)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
Vec3D (const Vec3D &) = default;
|
||||
|
||||
Vec3D (decltype (nullptr)) {
|
||||
|
|
@ -123,6 +181,14 @@ public:
|
|||
clear ();
|
||||
}
|
||||
|
||||
const float &operator [] (const int i) const {
|
||||
return &(x)[i];
|
||||
}
|
||||
|
||||
float &operator [] (const int i) {
|
||||
return &(x)[i];
|
||||
}
|
||||
|
||||
Vec3D &operator = (const Vec3D &) = default;
|
||||
|
||||
public:
|
||||
|
|
@ -131,11 +197,11 @@ public:
|
|||
}
|
||||
|
||||
T length2d () const {
|
||||
return cr::sqrtf (x * x + y * y);
|
||||
return cr::sqrtf (cr::square (x) + cr::square (y));
|
||||
}
|
||||
|
||||
T lengthSq () const {
|
||||
return x * x + y * y + z * z;
|
||||
return cr::square (x) + cr::square (y) + cr::square (z);
|
||||
}
|
||||
|
||||
Vec3D get2d () const {
|
||||
|
|
@ -143,6 +209,9 @@ public:
|
|||
}
|
||||
|
||||
Vec3D normalize () const {
|
||||
#if defined (CR_HAS_SSE)
|
||||
return SimdWrap <T> { x, y, z }.normalize ();
|
||||
#else
|
||||
auto len = length () + cr::kFloatCmpEpsilon;
|
||||
|
||||
if (cr::fzero (len)) {
|
||||
|
|
@ -150,9 +219,13 @@ public:
|
|||
}
|
||||
len = 1.0f / len;
|
||||
return { x * len, y * len, z * len };
|
||||
#endif
|
||||
}
|
||||
|
||||
Vec3D normalize2d () const {
|
||||
#if defined (CR_HAS_SSE)
|
||||
return SimdWrap <T> { x, y }.normalize ();
|
||||
#else
|
||||
auto len = length2d () + cr::kFloatCmpEpsilon;
|
||||
|
||||
if (cr::fzero (len)) {
|
||||
|
|
@ -160,6 +233,7 @@ public:
|
|||
}
|
||||
len = 1.0f / len;
|
||||
return { x * len, y * len, 0.0f };
|
||||
#endif
|
||||
}
|
||||
|
||||
bool empty () const {
|
||||
|
|
@ -179,24 +253,24 @@ public:
|
|||
}
|
||||
|
||||
T pitch () const {
|
||||
if (cr::fzero (x) && cr::fzero (y)) {
|
||||
if (cr::fzero (z)) {
|
||||
return 0.0f;
|
||||
}
|
||||
return cr::degreesToRadians (cr::atan2f (z, length2d ()));
|
||||
return cr::deg2rad (cr::atan2f (z, length2d ()));
|
||||
}
|
||||
|
||||
T yaw () const {
|
||||
if (cr::fzero (x) && cr::fzero (y)) {
|
||||
return 0.0f;
|
||||
}
|
||||
return cr::radiansToDegrees (cr:: atan2f (y, x));
|
||||
return cr::rad2deg (cr:: atan2f (y, x));
|
||||
}
|
||||
|
||||
Vec3D angles () const {
|
||||
if (cr::fzero (x) && cr::fzero (y)) {
|
||||
return { z > 0.0f ? 90.0f : 270.0f, 0.0, 0.0f };
|
||||
}
|
||||
return { cr::radiansToDegrees (cr::atan2f (z, length2d ())), cr::radiansToDegrees (cr::atan2f (y, x)), 0.0f };
|
||||
return { cr::rad2deg (cr::atan2f (z, length2d ())), cr::rad2deg (cr::atan2f (y, x)), 0.0f };
|
||||
}
|
||||
|
||||
void angleVectors (Vec3D *forward, Vec3D *right, Vec3D *upward) const {
|
||||
|
|
@ -206,7 +280,7 @@ public:
|
|||
T cosines[max] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// compute the sine and cosine compontents
|
||||
cr::sincosf (cr::degreesToRadians (x), cr::degreesToRadians (y), cr::degreesToRadians (z), sines, cosines);
|
||||
cr::sincosf (cr::deg2rad (x), cr::deg2rad (y), cr::deg2rad (z), sines, cosines);
|
||||
|
||||
if (forward) {
|
||||
*forward = {
|
||||
|
|
@ -214,7 +214,7 @@ typedef struct enginefuncs_s {
|
|||
void (*pfnCvar_DirectSet) (struct cvar_t *var, char *value);
|
||||
void (*pfnForceUnmodified) (FORCE_TYPE type, float *mins, float *maxs, const char *szFilename);
|
||||
void (*pfnGetPlayerStats) (const edict_t *client, int *ping, int *packet_loss);
|
||||
void (*pfnAddServerCommand) (char *cmd_name, void (*function) ());
|
||||
void (*pfnAddServerCommand) (const char *cmd_name, void (*function) ());
|
||||
|
||||
int (*pfnVoice_GetClientListening) (int iReceiver, int iSender);
|
||||
int (*pfnVoice_SetClientListening) (int iReceiver, int iSender, int bListen);
|
||||
|
|
@ -25,15 +25,19 @@ typedef int qboolean;
|
|||
typedef unsigned char byte;
|
||||
|
||||
#include <crlib/cr-vector.h>
|
||||
#include <crlib/cr-string.h>
|
||||
|
||||
// idea from regamedll
|
||||
class string_t final {
|
||||
class string_t final : public cr::DenyCopying {
|
||||
private:
|
||||
int offset;
|
||||
|
||||
public:
|
||||
explicit string_t () : offset (0) { }
|
||||
string_t (int offset) : offset (offset) { }
|
||||
explicit string_t () : offset (0)
|
||||
{ }
|
||||
|
||||
string_t (int offset) : offset (offset)
|
||||
{ }
|
||||
|
||||
~string_t () = default;
|
||||
|
||||
|
|
@ -101,11 +105,17 @@ static inline int MAKE_STRING (const char *val) {
|
|||
return static_cast <int> (ptrdiff);
|
||||
}
|
||||
#else
|
||||
#define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0)))
|
||||
#define MAKE_STRING(str) ((uint64)(str) - (uint64)(STRING(0)))
|
||||
#endif
|
||||
|
||||
inline const char *string_t::chars (size_t shift) const {
|
||||
return STRING (offset) + shift;
|
||||
auto result = STRING (offset);
|
||||
|
||||
return cr::strings.isEmpty (result) ? &cr::kNullChar : (result + shift);
|
||||
}
|
||||
|
||||
enum HLBool : int32 {
|
||||
HLFalse, HLTrue
|
||||
};
|
||||
|
||||
#endif // EXTDLL_H
|
||||
|
|
@ -1,6 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
* See the file "dllapi.h" in this folder for full information
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
// Simplified version by Wei Mingzhi
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -15,7 +22,7 @@ struct BotName {
|
|||
|
||||
public:
|
||||
BotName () = default;
|
||||
BotName (String &name, int usedBy) : name (cr::move (name)), usedBy (usedBy) { }
|
||||
BotName (StringRef name, int usedBy) : name (name), usedBy (usedBy) { }
|
||||
};
|
||||
|
||||
// voice config structure definition
|
||||
|
|
@ -25,7 +32,7 @@ struct ChatterItem {
|
|||
float duration;
|
||||
|
||||
public:
|
||||
ChatterItem (String name, float repeat, float duration) : name (cr::move (name)), repeat (repeat), duration (duration) { }
|
||||
ChatterItem (StringRef name, float repeat, float duration) : name (name), repeat (repeat), duration (duration) { }
|
||||
};
|
||||
|
||||
// language hasher
|
||||
|
|
@ -46,6 +53,14 @@ struct HashLangString {
|
|||
|
||||
// mostly config stuff, and some stuff dealing with menus
|
||||
class BotConfig final : public Singleton <BotConfig> {
|
||||
public:
|
||||
struct DifficultyData {
|
||||
float reaction[2] {};
|
||||
int32 headshotPct {};
|
||||
int32 seenThruPct {};
|
||||
int32 hearThruPct {};
|
||||
};
|
||||
|
||||
private:
|
||||
Array <StringArray> m_chat;
|
||||
Array <Array <ChatterItem>> m_chatter;
|
||||
|
|
@ -59,8 +74,9 @@ private:
|
|||
StringArray m_avatars;
|
||||
|
||||
Dictionary <String, String, HashLangString> m_language;
|
||||
Dictionary <int32, DifficultyData, IntNoHash <int32>> m_difficulty;
|
||||
|
||||
// default tables for personality weapon preferences, overridden by general.cfg
|
||||
// default tables for personality weapon preferences, overridden by weapon.cfg
|
||||
SmallArray <int32> m_normalWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 12, 10, 24, 25, 13, 11, 8, 7, 22, 23, 18, 21, 17, 19, 15, 17, 9, 14, 16 };
|
||||
SmallArray <int32> m_rusherWeaponPrefs = { 0, 2, 1, 4, 5, 6, 3, 24, 19, 22, 23, 20, 21, 10, 12, 13, 7, 8, 11, 9, 18, 17, 19, 25, 15, 16 };
|
||||
SmallArray <int32> m_carefulWeaponPrefs = { 0, 2, 1, 4, 25, 6, 3, 7, 8, 12, 10, 13, 11, 9, 24, 18, 14, 17, 16, 15, 19, 20, 21, 22, 23, 5 };
|
||||
|
|
@ -100,6 +116,9 @@ public:
|
|||
// load bots avatars config
|
||||
void loadAvatarsConfig ();
|
||||
|
||||
// load bots difficulty config
|
||||
void loadDifficultyConfig ();
|
||||
|
||||
// sets memfile to use engine functions
|
||||
void setupMemoryFiles ();
|
||||
|
||||
|
|
@ -119,12 +138,14 @@ public:
|
|||
WeaponInfo &findWeaponById (int id);
|
||||
|
||||
// translates bot message into needed language
|
||||
const char *translate (const char *input);
|
||||
const char *translate (StringRef input);
|
||||
|
||||
private:
|
||||
bool isCommentLine (const String &line) {
|
||||
const char ch = line.at (0);
|
||||
return ch == '#' || ch == '/' || ch == '\r' || ch == ';' || ch == 0 || ch == ' ';
|
||||
bool isCommentLine (StringRef line) const {
|
||||
if (line.empty ()) {
|
||||
return true;
|
||||
}
|
||||
return line.substr (0, 1).findFirstOf ("#/; \n\r") != String::InvalidIndex;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -140,7 +161,7 @@ public:
|
|||
}
|
||||
|
||||
// pick random phrase from chat bank
|
||||
const String &pickRandomFromChatBank (int chatType) {
|
||||
StringRef pickRandomFromChatBank (int chatType) {
|
||||
return m_chat[chatType].random ();
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +210,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// get's the difficulty level tweaks
|
||||
DifficultyData *getDifficultyTweaks (int32 level) {
|
||||
if (level < Difficulty::Noob || level > Difficulty::Expert) {
|
||||
return &m_difficulty[Difficulty::Expert];
|
||||
}
|
||||
return &m_difficulty[level];
|
||||
}
|
||||
|
||||
// get economics value
|
||||
int32 *getEconLimit () {
|
||||
return m_botBuyEconomyTable.data ();
|
||||
|
|
@ -200,7 +229,7 @@ public:
|
|||
}
|
||||
|
||||
// get's random avatar for player (if any)
|
||||
String getRandomAvatar () const {
|
||||
StringRef getRandomAvatar () const {
|
||||
if (!m_avatars.empty ()) {
|
||||
return m_avatars.random ();
|
||||
}
|
||||
|
|
@ -208,12 +237,12 @@ public:
|
|||
}
|
||||
|
||||
// get's random logo index
|
||||
int getRandomLogoIndex () const {
|
||||
return m_logos.index (m_logos.random ());
|
||||
int32 getRandomLogoIndex () const {
|
||||
return static_cast <int32> (m_logos.index (m_logos.random ()));
|
||||
}
|
||||
|
||||
// get random name by index
|
||||
const String &getRandomLogoName (int index) const {
|
||||
StringRef getRandomLogoName (int index) {
|
||||
return m_logos[index];
|
||||
}
|
||||
};
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -29,7 +36,7 @@ public:
|
|||
|
||||
public:
|
||||
BotCmd () = default;
|
||||
BotCmd (String name, String format, String help, Handler handler) : name (cr::move (name)), format (cr::move (format)), help (cr::move (help)), handler (cr::move (handler)) { }
|
||||
BotCmd (StringRef name, StringRef format, StringRef help, Handler handler) : name (name), format (format), help (help), handler (cr::move (handler)) { }
|
||||
};
|
||||
|
||||
// single bot menu
|
||||
|
|
@ -39,7 +46,7 @@ public:
|
|||
MenuHandler handler;
|
||||
|
||||
public:
|
||||
BotMenu (int ident, int slots, String text, MenuHandler handler) : ident (ident), slots (slots), text (cr::move (text)), handler (cr::move (handler)) { }
|
||||
BotMenu (int ident, int slots, StringRef text, MenuHandler handler) : ident (ident), slots (slots), text (text), handler (cr::move (handler)) { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -146,25 +153,16 @@ public:
|
|||
m_ent = ent;
|
||||
}
|
||||
|
||||
void fixMissingArgs (size_t num) {
|
||||
if (num < m_args.length ()) {
|
||||
return;
|
||||
}
|
||||
m_args.resize (num);
|
||||
}
|
||||
|
||||
int getInt (size_t arg) const {
|
||||
int intValue (size_t arg) const {
|
||||
if (!hasArg (arg)) {
|
||||
return 0;
|
||||
}
|
||||
return m_args[arg].int_ ();
|
||||
}
|
||||
|
||||
const String &getStr (size_t arg) {
|
||||
static String empty ("empty");
|
||||
|
||||
if (!hasArg (arg) || m_args[arg].empty ()) {
|
||||
return empty;
|
||||
StringRef strValue (size_t arg) {
|
||||
if (!hasArg (arg)) {
|
||||
return "";
|
||||
}
|
||||
return m_args[arg];
|
||||
}
|
||||
|
|
@ -182,7 +180,7 @@ public:
|
|||
}
|
||||
|
||||
// global heloer for sending message to correct channel
|
||||
template <typename ...Args> void msg (const char *fmt, Args ...args);
|
||||
template <typename ...Args> void msg (const char *fmt, Args &&...args);
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -197,7 +195,7 @@ public:
|
|||
};
|
||||
|
||||
// global heloer for sending message to correct channel
|
||||
template <typename ...Args> inline void BotControl::msg (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> inline void BotControl::msg (const char *fmt, Args &&...args) {
|
||||
auto result = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
|
||||
// if no receiver or many message have to appear, just print to server console
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -29,7 +36,7 @@ CR_DECLARE_SCOPED_ENUM (Var,
|
|||
ReadOnly,
|
||||
Password,
|
||||
NoServer,
|
||||
NoRegister
|
||||
GameRef
|
||||
)
|
||||
|
||||
// supported cs's
|
||||
|
|
@ -67,15 +74,16 @@ CR_DECLARE_SCOPED_ENUM (EntitySearchResult,
|
|||
)
|
||||
|
||||
// variable reg pair
|
||||
struct VarPair {
|
||||
Var type;
|
||||
struct ConVarReg {
|
||||
cvar_t reg;
|
||||
bool missing;
|
||||
const char *regval;
|
||||
class ConVar *self;
|
||||
String info;
|
||||
String init;
|
||||
String regval;
|
||||
class ConVar *self;
|
||||
float initial, min, max;
|
||||
bool missing;
|
||||
bool bounded;
|
||||
int32 type;
|
||||
};
|
||||
|
||||
// entity prototype
|
||||
|
|
@ -122,13 +130,14 @@ private:
|
|||
edict_t *m_localEntity;
|
||||
|
||||
Array <edict_t *> m_breakables;
|
||||
SmallArray <VarPair> m_cvars;
|
||||
SmallArray <ConVarReg> m_cvars;
|
||||
SharedLibrary m_gameLib;
|
||||
EngineWrap m_engineWrap;
|
||||
|
||||
bool m_precached;
|
||||
int m_gameFlags;
|
||||
int m_mapFlags;
|
||||
|
||||
int m_gameFlags {};
|
||||
int m_mapFlags {};
|
||||
|
||||
float m_slowFrame; // per second updated frame
|
||||
|
||||
|
|
@ -149,6 +158,9 @@ public:
|
|||
// test line
|
||||
void testLine (const Vector &start, const Vector &end, int ignoreFlags, edict_t *ignoreEntity, TraceResult *ptr);
|
||||
|
||||
// trace line with channel, but allows us to store last traceline bot has fired, saving us some cpu cycles
|
||||
bool testLineChannel (TraceChannel channel, const Vector &start, const Vector &end, int ignoreFlags, edict_t *ignoreEntity, TraceResult *ptr);
|
||||
|
||||
// test line
|
||||
void testHull (const Vector &start, const Vector &end, int ignoreFlags, int hullNumber, edict_t *ignoreEntity, TraceResult *ptr);
|
||||
|
||||
|
|
@ -177,7 +189,7 @@ public:
|
|||
void prepareBotArgs (edict_t *ent, String str);
|
||||
|
||||
// adds cvar to registration stack
|
||||
void addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, class ConVar *self);
|
||||
void addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, int32 varType, bool missingAction, const char *regval, class ConVar *self);
|
||||
|
||||
// check the cvar bounds
|
||||
void checkCvarsBounds ();
|
||||
|
|
@ -201,10 +213,10 @@ public:
|
|||
void slowFrame ();
|
||||
|
||||
// search entities by variable field
|
||||
void searchEntities (const String &field, const String &value, EntitySearch functor);
|
||||
void searchEntities (StringRef field, StringRef value, EntitySearch functor);
|
||||
|
||||
// search entities in sphere
|
||||
void searchEntities (const Vector &position, const float radius, EntitySearch functor);
|
||||
void searchEntities (const Vector &position, float radius, EntitySearch functor);
|
||||
|
||||
// this function is checking that pointed by ent pointer obstacle, can be destroyed
|
||||
bool isShootableBreakable (edict_t *ent);
|
||||
|
|
@ -228,7 +240,7 @@ public:
|
|||
|
||||
// gets custom engine args for client command
|
||||
const char *botArgs () const {
|
||||
return strings.format (String::join (m_botArgs, " ", m_botArgs[0] == "say" || m_botArgs[0] == "say_team" ? 1 : 0).chars ());
|
||||
return strings.format (String::join (m_botArgs, " ", m_botArgs[0].startsWith ("say") ? 1 : 0).chars ());
|
||||
}
|
||||
|
||||
// gets custom engine argv for client command
|
||||
|
|
@ -240,8 +252,8 @@ public:
|
|||
}
|
||||
|
||||
// gets custom engine argc for client command
|
||||
int botArgc () const {
|
||||
return m_botArgs.length ();
|
||||
int32 botArgc () const {
|
||||
return m_botArgs.length <int32> ();
|
||||
}
|
||||
|
||||
// gets edict pointer out of entity index
|
||||
|
|
@ -329,7 +341,7 @@ public:
|
|||
}
|
||||
|
||||
// get registered cvars list
|
||||
const SmallArray <VarPair> &getCvars () {
|
||||
const SmallArray <ConVarReg> &getCvars () {
|
||||
return m_cvars;
|
||||
}
|
||||
|
||||
|
|
@ -347,22 +359,22 @@ public:
|
|||
void sendClientMessage (bool console, edict_t *ent, const char *message);
|
||||
|
||||
// send server command
|
||||
template <typename ...Args> void serverCommand (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void serverCommand (const char *fmt, Args &&...args) {
|
||||
engfuncs.pfnServerCommand (strings.concat (strings.format (fmt, cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
|
||||
}
|
||||
|
||||
// send a bot command
|
||||
template <typename ...Args> void botCommand (edict_t *ent, const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void botCommand (edict_t *ent, const char *fmt, Args &&...args) {
|
||||
prepareBotArgs (ent, strings.format (fmt, cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
// prints data to servers console
|
||||
template <typename ...Args> void print (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void print (const char *fmt, Args &&...args) {
|
||||
engfuncs.pfnServerPrint (strings.concat (strings.format (conf.translate (fmt), cr::forward <Args> (args)...), "\n", StringBuffer::StaticBufferSize));
|
||||
}
|
||||
|
||||
// prints center message to specified player
|
||||
template <typename ...Args> void clientPrint (edict_t *ent, const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void clientPrint (edict_t *ent, const char *fmt, Args &&...args) {
|
||||
if (isNullEntity (ent)) {
|
||||
print (fmt, cr::forward <Args> (args)...);
|
||||
return;
|
||||
|
|
@ -371,7 +383,7 @@ public:
|
|||
}
|
||||
|
||||
// prints message to client console
|
||||
template <typename ...Args> void centerPrint (edict_t *ent, const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void centerPrint (edict_t *ent, const char *fmt, Args &&...args) {
|
||||
if (isNullEntity (ent)) {
|
||||
print (fmt, cr::forward <Args> (args)...);
|
||||
return;
|
||||
|
|
@ -390,12 +402,12 @@ public:
|
|||
~ConVar () = default;
|
||||
|
||||
public:
|
||||
ConVar (const char *name, const char *initval, Var type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
|
||||
Game::get ().addNewCvar (name, initval, "", false, 0.0f, 0.0f, type, regMissing, regVal, this);
|
||||
ConVar (const char *name, const char *initval, int32 type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
|
||||
Game::instance ().addNewCvar (name, initval, "", false, 0.0f, 0.0f, type, regMissing, regVal, this);
|
||||
}
|
||||
|
||||
ConVar (const char *name, const char *initval, const char *info, bool bounded = true, float min = 0.0f, float max = 1.0f, Var type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
|
||||
Game::get ().addNewCvar (name, initval, info, bounded, min, max, type, regMissing, regVal, this);
|
||||
ConVar (const char *name, const char *initval, const char *info, bool bounded = true, float min = 0.0f, float max = 1.0f, int32 type = Var::NoServer, bool regMissing = false, const char *regVal = nullptr) : ptr (nullptr) {
|
||||
Game::instance ().addNewCvar (name, initval, info, bounded, min, max, type, regMissing, regVal, this);
|
||||
}
|
||||
|
||||
bool bool_ () const {
|
||||
|
|
@ -497,8 +509,8 @@ public:
|
|||
|
||||
class LightMeasure final : public Singleton <LightMeasure> {
|
||||
private:
|
||||
lightstyle_t m_lightstyle[MAX_LIGHTSTYLES];
|
||||
int m_lightstyleValue[MAX_LIGHTSTYLEVALUE];
|
||||
lightstyle_t m_lightstyle[MAX_LIGHTSTYLES] {};
|
||||
int m_lightstyleValue[MAX_LIGHTSTYLEVALUE] {};
|
||||
bool m_doAnimation = false;
|
||||
|
||||
Color m_point;
|
||||
|
|
@ -587,7 +599,7 @@ public:
|
|||
if (m_buffer.length () < m_cursor) {
|
||||
return;
|
||||
}
|
||||
for (; m_cursor < m_buffer.length () && m_buffer[m_cursor] != '\0'; ++m_cursor) { }
|
||||
for (; m_cursor < m_buffer.length () && m_buffer[m_cursor] != kNullChar; ++m_cursor) { }
|
||||
++m_cursor;
|
||||
}
|
||||
|
||||
|
|
@ -603,27 +615,23 @@ public:
|
|||
|
||||
// for android
|
||||
#if defined (CR_ANDROID) && defined(CR_ARCH_ARM)
|
||||
extern "C" void player (entvars_t *pev);
|
||||
extern "C" void player (entvars_t *);
|
||||
#endif
|
||||
|
||||
class DynamicEntityLink : public Singleton <DynamicEntityLink> {
|
||||
class EntityLinkage : public Singleton <EntityLinkage> {
|
||||
private:
|
||||
#if defined (CR_WINDOWS)
|
||||
# define MODULE_HANDLE HMODULE
|
||||
# define MODULE_SYMBOL GetProcAddress
|
||||
# define HOOK_FUNCTION GetProcAddress
|
||||
# define HOOK_CAST HMODULE
|
||||
#else
|
||||
# define MODULE_HANDLE void *
|
||||
# define MODULE_SYMBOL dlsym
|
||||
# define HOOK_FUNCTION dlsym
|
||||
# define HOOK_CAST SharedLibrary::Handle
|
||||
#endif
|
||||
|
||||
private:
|
||||
using Handle = void *;
|
||||
using Name = const char *;
|
||||
|
||||
private:
|
||||
template <typename K> struct FunctionHash {
|
||||
uint32 operator () (Name key) const {
|
||||
char *str = const_cast <char *> (key);
|
||||
template <typename K> struct CharHash {
|
||||
uint32 operator () (const char *key) const {
|
||||
auto str = const_cast <char *> (key);
|
||||
uint32 hash = 0;
|
||||
|
||||
while (*str++) {
|
||||
|
|
@ -636,41 +644,34 @@ private:
|
|||
private:
|
||||
SharedLibrary m_self;
|
||||
SimpleHook m_dlsym;
|
||||
Dictionary <Name, Handle, FunctionHash <Name>> m_exports;
|
||||
Dictionary <const char *, SharedLibrary::Handle, CharHash <const char *>> m_exports;
|
||||
|
||||
public:
|
||||
DynamicEntityLink () = default;
|
||||
EntityLinkage () = default;
|
||||
|
||||
~DynamicEntityLink () {
|
||||
~EntityLinkage () {
|
||||
m_dlsym.disable ();
|
||||
}
|
||||
public:
|
||||
Handle search (Handle module, Name function);
|
||||
void initialize ();
|
||||
SharedLibrary::Handle lookup (SharedLibrary::Handle module, const char *function);
|
||||
|
||||
public:
|
||||
void initialize () {
|
||||
if (plat.arm) {
|
||||
return;
|
||||
}
|
||||
m_dlsym.patch (reinterpret_cast <void *> (&MODULE_SYMBOL), reinterpret_cast <void *> (&DynamicEntityLink::replacement));
|
||||
m_self.locate (&engfuncs);
|
||||
}
|
||||
|
||||
EntityFunction getPlayerFunction () {
|
||||
#if defined (CR_ANDROID) && defined(CR_ARCH_ARM)
|
||||
return player;
|
||||
void callPlayerFunction (edict_t *ent) {
|
||||
#if defined (CR_ANDROID) && defined (CR_ARCH_ARM)
|
||||
player (&ent->v);
|
||||
#else
|
||||
return reinterpret_cast <EntityFunction> (search (Game::get ().lib ().handle (), "player"));
|
||||
reinterpret_cast <EntityFunction> (lookup (Game::instance ().lib ().handle (), "player")) (&ent->v);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
static Handle CR_STDCALL replacement (Handle module, Name function) {
|
||||
return DynamicEntityLink::get ().search (module, function);
|
||||
static SharedLibrary::Handle CR_STDCALL replacement (SharedLibrary::Handle module, const char *function) {
|
||||
return EntityLinkage::instance ().lookup (module, function);
|
||||
}
|
||||
};
|
||||
|
||||
// expose globals
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Game, game);
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (LightMeasure, illum);
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (DynamicEntityLink, ents);
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (EntityLinkage, ents);
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -319,8 +326,9 @@ public:
|
|||
bool saveGraphData ();
|
||||
bool loadGraphData ();
|
||||
|
||||
template <typename U> bool saveStorage (const String &ext, const String &name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
|
||||
template <typename U> bool loadStorage (const String &ext, const String &name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32 *outOptions);
|
||||
template <typename U> bool saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
|
||||
template <typename U> bool loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32 *outOptions);
|
||||
template <typename ...Args> bool raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args);
|
||||
|
||||
void saveOldFormat ();
|
||||
void initGraph ();
|
||||
|
|
@ -416,8 +424,8 @@ public:
|
|||
}
|
||||
|
||||
// get real nodes num
|
||||
int length () const {
|
||||
return m_paths.length ();
|
||||
int32 length () const {
|
||||
return m_paths.length <int32> ();
|
||||
}
|
||||
|
||||
// check if has editor
|
||||
|
|
@ -436,5 +444,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// we're need `bots`
|
||||
#include <manager.h>
|
||||
|
||||
// helper for reporting load errors
|
||||
template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args) {
|
||||
auto result = strings.format (fmt, cr::forward <Args> (args)...);
|
||||
logger.error (result);
|
||||
|
||||
// if graph reset paths
|
||||
if (isGraph) {
|
||||
bots.kickEveryone (true);
|
||||
|
||||
m_tempStrings = result;
|
||||
m_paths.clear ();
|
||||
}
|
||||
file.close ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// explose global
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (BotGraph, graph);
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -18,6 +25,36 @@ struct BotRequest {
|
|||
String name;
|
||||
};
|
||||
|
||||
// initial frustum data
|
||||
struct FrustumData : public Singleton <FrustumData> {
|
||||
private:
|
||||
float Fov = 75.0f;
|
||||
float AspectRatio = 1.33333f;
|
||||
|
||||
public:
|
||||
float MaxView = 4096.0f;
|
||||
float MinView = 5.0f;
|
||||
|
||||
public:
|
||||
float farHeight; // height of the far frustum
|
||||
float farWidth; // width of the far frustum
|
||||
|
||||
float nearHeight; // height of the near frustum
|
||||
float nearWidth; // width of the near frustum
|
||||
|
||||
public:
|
||||
FrustumData () {
|
||||
nearHeight = 2.0f * cr::tanf (Fov * 0.0174532925f * 0.5f) * MinView;
|
||||
nearWidth = nearHeight * AspectRatio;
|
||||
|
||||
farHeight = 2.0f * cr::tanf (Fov * 0.0174532925f * 0.5f) * MaxView;
|
||||
farWidth = farHeight * AspectRatio;
|
||||
}
|
||||
};
|
||||
|
||||
// declare global frustum data
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (FrustumData, frustum);
|
||||
|
||||
// manager class
|
||||
class BotManager final : public Singleton <BotManager> {
|
||||
public:
|
||||
|
|
@ -58,9 +95,10 @@ private:
|
|||
SmallArray <UniqueBot> m_bots; // all available bots
|
||||
|
||||
edict_t *m_killerEntity; // killer entity for bots
|
||||
FrustumData m_frustumData {};
|
||||
|
||||
protected:
|
||||
BotCreateResult create (const String &name, int difficulty, int personality, int team, int member);
|
||||
BotCreateResult create (StringRef name, int difficulty, int personality, int team, int member);
|
||||
|
||||
public:
|
||||
BotManager ();
|
||||
|
|
@ -77,8 +115,8 @@ public:
|
|||
|
||||
int getHumansCount (bool ignoreSpectators = false);
|
||||
int getAliveHumansCount ();
|
||||
int getBotCount ();
|
||||
float getConnectionTime (int botId);
|
||||
|
||||
float getConnectTime (int botId, float original);
|
||||
|
||||
void setBombPlanted (bool isPlanted);
|
||||
void frame ();
|
||||
|
|
@ -86,8 +124,8 @@ public:
|
|||
void destroyKillerEntity ();
|
||||
void touchKillerEntity (Bot *bot);
|
||||
void destroy ();
|
||||
void addbot (const String &name, int difficulty, int personality, int team, int member, bool manual);
|
||||
void addbot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool manual);
|
||||
void addbot (StringRef name, int difficulty, int personality, int team, int member, bool manual);
|
||||
void addbot (StringRef name, StringRef difficulty, StringRef personality, StringRef team, StringRef member, bool manual);
|
||||
void serverFill (int selection, int personality = Personality::Normal, int difficulty = -1, int numToAdd = -1);
|
||||
void kickEveryone (bool instant = false, bool zeroQuota = true);
|
||||
void kickBot (int index);
|
||||
|
|
@ -95,6 +133,7 @@ public:
|
|||
void killAllBots (int team = -1);
|
||||
void maintainQuota ();
|
||||
void maintainAutoKill ();
|
||||
void maintainLeaders ();
|
||||
void initQuota ();
|
||||
void initRound ();
|
||||
void decrementQuota (int by = 1);
|
||||
|
|
@ -110,7 +149,7 @@ public:
|
|||
void updateIntrestingEntities ();
|
||||
void captureChatRadio (const char *cmd, const char *arg, edict_t *ent);
|
||||
void notifyBombDefuse ();
|
||||
void execGameEntity (entvars_t *vars);
|
||||
void execGameEntity (edict_t *ent);
|
||||
void forEach (ForEachBot handler);
|
||||
void erase (Bot *bot);
|
||||
void handleDeath (edict_t *killer, edict_t *victim);
|
||||
|
|
@ -120,11 +159,11 @@ public:
|
|||
bool kickRandom (bool decQuota = true, Team fromTeam = Team::Unassigned);
|
||||
|
||||
public:
|
||||
const Array <edict_t *> &searchActiveGrenades () {
|
||||
const Array <edict_t *> &getActiveGrenades () {
|
||||
return m_activeGrenades;
|
||||
}
|
||||
|
||||
const Array <edict_t *> &searchIntrestingEntities () {
|
||||
const Array <edict_t *> &getIntrestingEntities () {
|
||||
return m_intrestingEntities;
|
||||
}
|
||||
|
||||
|
|
@ -140,10 +179,14 @@ public:
|
|||
return m_economicsGood[team];
|
||||
}
|
||||
|
||||
int getLastWinner () const {
|
||||
int32 getLastWinner () const {
|
||||
return m_lastWinner;
|
||||
}
|
||||
|
||||
int32 getBotCount () {
|
||||
return m_bots.length <int32> ();
|
||||
}
|
||||
|
||||
// get the list of filters
|
||||
SmallArray <BotTask> &getFilters () {
|
||||
return m_filters;
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -86,8 +93,8 @@ private:
|
|||
Dictionary <String, int32> m_teamInfoCache; // cache for teaminfo message
|
||||
|
||||
private:
|
||||
Bot *m_bot; // owner of a message
|
||||
NetMsg m_current; // ongoing message id
|
||||
Bot *m_bot {}; // owner of a message
|
||||
NetMsg m_current {}; // ongoing message id
|
||||
|
||||
SmallArray <Args> m_args; // args collected from write* functions
|
||||
Dictionary <String, NetMsg> m_wanted; // wanted messages
|
||||
|
|
@ -120,7 +127,7 @@ public:
|
|||
~MessageDispatcher () = default;
|
||||
|
||||
public:
|
||||
int32 add (const String &name, int32 id);
|
||||
int32 add (StringRef name, int32 id);
|
||||
int32 id (NetMsg msg);
|
||||
|
||||
void start (edict_t *ent, int32 type);
|
||||
53
inc/product.h
Normal file
53
inc/product.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef VERSION_GENERATED
|
||||
# define VERSION_HEADER <version.build.h>
|
||||
#else
|
||||
# define VERSION_HEADER <version.h>
|
||||
#endif
|
||||
|
||||
#include VERSION_HEADER
|
||||
|
||||
// simple class for bot internal information
|
||||
class Product final : public Singleton <Product> {
|
||||
public:
|
||||
const struct Build {
|
||||
const StringRef hash { MODULE_BUILD_HASH };
|
||||
const StringRef author { MODULE_BUILD_AUTHOR };
|
||||
const StringRef count { MODULE_BUILD_COUNT };
|
||||
const StringRef machine { MODULE_BUILD_MACHINE };
|
||||
const StringRef compiler { MODULE_BUILD_COMPILER };
|
||||
const StringRef id { MODULE_BOT_BUILD_ID };
|
||||
} build { };
|
||||
|
||||
public:
|
||||
const StringRef name { "YaPB" };
|
||||
const StringRef year { __DATE__ + 8 };
|
||||
const StringRef author { "YaPB Development Team" };
|
||||
const StringRef email { "team@yapb.ru" };
|
||||
const StringRef url { "https://yapb.ru/" };
|
||||
const StringRef download { "http://data.yapb.ru/" };
|
||||
const StringRef folder { "yapb" };
|
||||
const StringRef logtag { "YB" };
|
||||
const StringRef dtime { __DATE__ " " __TIME__ };
|
||||
const StringRef date { __DATE__ };
|
||||
const StringRef version { MODULE_BOT_VERSION };
|
||||
};
|
||||
|
||||
// expose product info
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Product, product);
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
|
@ -20,7 +27,7 @@ CR_DECLARE_SCOPED_ENUM (Noise,
|
|||
Door = cr::bit (7)
|
||||
)
|
||||
|
||||
class BotUtils final : public Singleton <BotUtils> {
|
||||
class BotSupport final : public Singleton <BotSupport> {
|
||||
private:
|
||||
bool m_needToSendWelcome;
|
||||
float m_welcomeReceiveTime;
|
||||
|
|
@ -34,18 +41,15 @@ private:
|
|||
SimpleHook m_sendToHook;
|
||||
|
||||
public:
|
||||
BotUtils ();
|
||||
~BotUtils () = default;
|
||||
BotSupport ();
|
||||
~BotSupport () = default;
|
||||
|
||||
public:
|
||||
// need to send welcome message ?
|
||||
void checkWelcome ();
|
||||
|
||||
// converts weapon id to alias name
|
||||
const String &weaponIdToAlias (const int32 id);
|
||||
|
||||
// gets the build number of bot
|
||||
int buildNumber ();
|
||||
StringRef weaponIdToAlias (int32 id);
|
||||
|
||||
// check if origin is visible from the entity side
|
||||
bool isVisible (const Vector &origin, edict_t *ent);
|
||||
|
|
@ -72,7 +76,7 @@ public:
|
|||
void traceDecals (entvars_t *pev, TraceResult *trace, int logotypeIndex);
|
||||
|
||||
// attaches sound to client struct
|
||||
void listenNoise (edict_t *ent, const String &sample, float volume);
|
||||
void listenNoise (edict_t *ent, StringRef sample, float volume);
|
||||
|
||||
// simulate sound for players
|
||||
void simulateNoise (int playerIndex);
|
||||
|
|
@ -90,7 +94,7 @@ public:
|
|||
void addChatErrors (String &line);
|
||||
|
||||
// chat helper to find keywords for given string
|
||||
bool checkKeywords (const String &line, String &reply);
|
||||
bool checkKeywords (StringRef line, String &reply);
|
||||
|
||||
// generates ping bitmask for SVC_PINGS message
|
||||
int getPingBitmask (edict_t *ent, int loss, int ping);
|
||||
|
|
@ -104,6 +108,8 @@ public:
|
|||
// installs the sendto function intreception
|
||||
void installSendTo ();
|
||||
|
||||
// check if object inside frustum plane
|
||||
bool isObjectInsidePlane (FrustumPlane &plane, const Vector ¢er, float height, float radius);
|
||||
public:
|
||||
|
||||
// re-show welcome after changelevel ?
|
||||
|
|
@ -143,7 +149,7 @@ public:
|
|||
|
||||
// check if origin is inside view cone of entity
|
||||
bool isInViewCone (const Vector &origin, edict_t *ent) {
|
||||
return getShootingCone (ent, origin) >= cr::cosf (cr::degreesToRadians ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
||||
return getShootingCone (ent, origin) >= cr::cosf (cr::deg2rad ((ent->v.fov > 0 ? ent->v.fov : 90.0f) * 0.5f));
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -151,4 +157,4 @@ public:
|
|||
};
|
||||
|
||||
// explose global
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (BotUtils, util);
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (BotSupport, util);
|
||||
27
inc/version.h
Normal file
27
inc/version.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// fallback if no git or custom build
|
||||
#define MODULE_BUILD_HASH "0"
|
||||
#define MODULE_BUILD_AUTHOR "team@yapb.ru"
|
||||
#define MODULE_BUILD_COUNT "0"
|
||||
#define MODULE_BUILD_MACHINE "localhost"
|
||||
#define MODULE_BUILD_COMPILER "unknown"
|
||||
|
||||
#define MODULE_BOT_VERSION "4.0.0"
|
||||
#define MODULE_BOT_VERSION_FILE 4,0,0,000
|
||||
#define MODULE_BOT_BUILD_ID "0:0"
|
||||
28
inc/version.h.in
Normal file
28
inc/version.h.in
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// generated by meson build system
|
||||
#ifndef MODULE_BUILD_HASH
|
||||
# define MODULE_BUILD_HASH "@commitHash@"
|
||||
# define MODULE_BUILD_AUTHOR @commitAuthor@
|
||||
# define MODULE_BUILD_COUNT "@commitCount@"
|
||||
# define MODULE_BUILD_MACHINE "@buildMachine@"
|
||||
# define MODULE_BUILD_COMPILER "@buildCompiler@"
|
||||
# define MODULE_BOT_VERSION "@buildVersion@"
|
||||
# define MODULE_BOT_VERSION_FILE @buildVersionWin@,@commitCount@
|
||||
# define MODULE_BOT_BUILD_ID "@commitCount@:@commitHash@"
|
||||
#endif
|
||||
|
|
@ -1,22 +1,29 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <engine/extdll.h>
|
||||
#include <engine/metamod.h>
|
||||
#include <hlsdk/extdll.h>
|
||||
#include <hlsdk/metamod.h>
|
||||
|
||||
#include <crlib/cr-complete.h>
|
||||
|
||||
// use all the cr-library
|
||||
using namespace cr;
|
||||
|
||||
#include <resource.h>
|
||||
#include <product.h>
|
||||
|
||||
// forwards
|
||||
class Bot;
|
||||
|
|
@ -101,11 +108,11 @@ CR_DECLARE_SCOPED_ENUM (Personality,
|
|||
|
||||
// bot difficulties
|
||||
CR_DECLARE_SCOPED_ENUM (Difficulty,
|
||||
VeryEasy,
|
||||
Noob,
|
||||
Easy,
|
||||
Normal,
|
||||
Hard,
|
||||
Extreme,
|
||||
Expert,
|
||||
Invalid = -1
|
||||
)
|
||||
|
||||
|
|
@ -274,9 +281,9 @@ CR_DECLARE_SCOPED_ENUM (BuyState,
|
|||
PrimaryWeapon = 0,
|
||||
ArmorVestHelm,
|
||||
SecondaryWeapon,
|
||||
Grenades,
|
||||
DefusalKit,
|
||||
Ammo,
|
||||
DefusalKit,
|
||||
Grenades,
|
||||
NightVision,
|
||||
Done
|
||||
)
|
||||
|
|
@ -367,7 +374,8 @@ CR_DECLARE_SCOPED_ENUM (AimFlags,
|
|||
Entity = cr::bit (4), // aim at entity like buttons, hostages
|
||||
Enemy = cr::bit (5), // aim at enemy
|
||||
Grenade = cr::bit (6), // aim for grenade throw
|
||||
Override = cr::bit (7) // overrides all others (blinded)
|
||||
Override = cr::bit (7), // overrides all others (blinded)
|
||||
Danger = cr::bit (8) // additional danger falg
|
||||
)
|
||||
|
||||
// famas/glock burst mode status + m4a1/usp silencer
|
||||
|
|
@ -384,6 +392,24 @@ CR_DECLARE_SCOPED_ENUM (Visibility,
|
|||
None = 0
|
||||
)
|
||||
|
||||
// channel for skip traceline
|
||||
CR_DECLARE_SCOPED_ENUM (TraceChannel,
|
||||
Enemy = 0,
|
||||
Body,
|
||||
Num
|
||||
)
|
||||
|
||||
// frustum sides
|
||||
CR_DECLARE_SCOPED_ENUM (FrustumSide,
|
||||
Top = 0,
|
||||
Bottom,
|
||||
Left,
|
||||
Right,
|
||||
Near,
|
||||
Far,
|
||||
Num
|
||||
)
|
||||
|
||||
// some hardcoded desire defines used to override calculated ones
|
||||
namespace TaskPri {
|
||||
static constexpr float Normal { 35.0f };
|
||||
|
|
@ -407,8 +433,8 @@ namespace TaskPri {
|
|||
// storage file magic
|
||||
constexpr char kPodbotMagic[8] = "PODWAY!";
|
||||
|
||||
constexpr int32 kStorageMagic = 0x59415042;
|
||||
constexpr int32 kStorageMagicUB = 0x544f4255; // storage magic for ubot-data files
|
||||
constexpr int32 kStorageMagic = 0x59415042; // storage magic for yapb-data files
|
||||
constexpr int32 kStorageMagicUB = 0x544f4255; //support also the fork format (merged back into yapb)
|
||||
|
||||
constexpr float kInfiniteDistance = 9999999.0f;
|
||||
constexpr float kGrenadeCheckTime = 2.15f;
|
||||
|
|
@ -437,9 +463,6 @@ constexpr int kMaxNodesInsideBucket = kMaxBucketSize / kMaxBucketsInsidePos;
|
|||
constexpr auto kPrimaryWeaponMask = (cr::bit (Weapon::XM1014) | cr::bit (Weapon::M3) | cr::bit (Weapon::MAC10) | cr::bit (Weapon::UMP45) | cr::bit (Weapon::MP5) | cr::bit (Weapon::TMP) | cr::bit (Weapon::P90) | cr::bit (Weapon::AUG) | cr::bit (Weapon::M4A1) | cr::bit (Weapon::SG552) | cr::bit (Weapon::AK47) | cr::bit (Weapon::Scout) | cr::bit (Weapon::SG550) | cr::bit (Weapon::AWP) | cr::bit (Weapon::G3SG1) | cr::bit (Weapon::M249) | cr::bit (Weapon::Famas) | cr::bit (Weapon::Galil));
|
||||
constexpr auto kSecondaryWeaponMask = (cr::bit (Weapon::P228) | cr::bit (Weapon::Elite) | cr::bit (Weapon::USP) | cr::bit (Weapon::Glock18) | cr::bit (Weapon::Deagle) | cr::bit (Weapon::FiveSeven));
|
||||
|
||||
// include bot graph stuff
|
||||
#include <graph.h>
|
||||
|
||||
// links keywords and replies together
|
||||
struct Keywords {
|
||||
StringArray keywords;
|
||||
|
|
@ -530,6 +553,13 @@ struct ClientNoise {
|
|||
float last;
|
||||
};
|
||||
|
||||
// defines frustum data for bot
|
||||
struct FrustumPlane {
|
||||
Vector normal;
|
||||
Vector point;
|
||||
float result;
|
||||
};
|
||||
|
||||
// array of clients struct
|
||||
struct Client {
|
||||
edict_t *ent; // pointer to actual edict
|
||||
|
|
@ -556,6 +586,9 @@ struct ChatCollection {
|
|||
StringArray lastUsedSentences;
|
||||
};
|
||||
|
||||
// include bot graph stuff
|
||||
#include <graph.h>
|
||||
|
||||
// main bot class
|
||||
class Bot final {
|
||||
private:
|
||||
|
|
@ -572,11 +605,12 @@ private:
|
|||
uint32 m_aimFlags; // aiming conditions
|
||||
uint32 m_currentTravelFlags; // connection flags like jumping
|
||||
|
||||
int m_traceSkip[TraceChannel::Num]; // trace need to be skipped?
|
||||
int m_messageQueue[32]; // stack for messages
|
||||
|
||||
int m_oldButtons; // our old buttons
|
||||
int m_reloadState; // current reload state
|
||||
int m_voicePitch; // bot voice pitch
|
||||
int m_rechoiceGoalCount; // multiple failed goals?
|
||||
int m_loosedBombNodeIndex; // nearest to loosed bomb node
|
||||
int m_plantedBombNodeIndex; // nearest to planted bomb node
|
||||
int m_currentNodeIndex; // current node index
|
||||
|
|
@ -618,7 +652,6 @@ private:
|
|||
float m_firstCollideTime; // time of first collision
|
||||
float m_probeTime; // time of probing different moves
|
||||
float m_lastCollTime; // time until next collision check
|
||||
float m_jumpStateTimer; // timer for jumping collision check
|
||||
float m_lookYawVel; // look yaw velocity
|
||||
float m_lookPitchVel; // look pitch velocity
|
||||
float m_lookUpdateTime; // lookangles update time
|
||||
|
|
@ -668,6 +701,7 @@ private:
|
|||
CollisionState m_collisionState; // collision State
|
||||
FindPath m_pathType; // which pathfinder to use
|
||||
uint8 m_enemyParts; // visibility flags
|
||||
TraceResult m_lastTrace[TraceChannel::Num]; // last trace result
|
||||
|
||||
edict_t *m_pickupItem; // pointer to entity of item to use/pickup
|
||||
edict_t *m_itemIgnore; // pointer to entity to ignore for pickup
|
||||
|
|
@ -699,6 +733,7 @@ private:
|
|||
BinaryHeap <RouteTwin> m_routeQue;
|
||||
Path *m_path; // pointer to the current path node
|
||||
String m_chatBuffer; // space for strings (say text...)
|
||||
FrustumPlane m_frustum[FrustumSide::Num] {};
|
||||
|
||||
private:
|
||||
int pickBestWeapon (int *vec, int count, int moneySave);
|
||||
|
|
@ -747,8 +782,8 @@ private:
|
|||
bool hasActiveGoal ();
|
||||
bool advanceMovement ();
|
||||
bool isBombDefusing (const Vector &bombOrigin);
|
||||
bool isOccupiedNode (int index);
|
||||
bool seesItem (const Vector &dest, const char *itemName);
|
||||
bool isOccupiedNode (int index, bool needZeroVelocity = false);
|
||||
bool seesItem (const Vector &dest, const char *classname);
|
||||
bool lastEnemyShootable ();
|
||||
bool rateGroundWeapon (edict_t *ent);
|
||||
bool reactOnEnemy ();
|
||||
|
|
@ -765,6 +800,7 @@ private:
|
|||
bool isPenetrableObstacle (const Vector &dest);
|
||||
bool isPenetrableObstacle2 (const Vector &dest);
|
||||
bool isEnemyBehindShield (edict_t *enemy);
|
||||
bool isEnemyInFrustum (edict_t *enemy);
|
||||
bool checkChatKeywords (String &reply);
|
||||
bool isReplyingToChat ();
|
||||
bool isReachableNode (int index);
|
||||
|
|
@ -792,7 +828,7 @@ private:
|
|||
void updateLookAnglesNewbie (const Vector &direction, float delta);
|
||||
void setIdealReactionTimers (bool actual = false);
|
||||
void updateHearing ();
|
||||
void postprocessGoals (const IntArray &goals, int *result);
|
||||
void postprocessGoals (const IntArray &goals, int result[]);
|
||||
void updatePickups ();
|
||||
void checkTerrain (float movedDistance, const Vector &dirNormal);
|
||||
void checkDarkness ();
|
||||
|
|
@ -801,6 +837,8 @@ private:
|
|||
void updatePracticeValue (int damage);
|
||||
void updatePracticeDamage (edict_t *attacker, int damage);
|
||||
void findShortestPath (int srcIndex, int destIndex);
|
||||
void calculateFrustum ();
|
||||
|
||||
void findPath (int srcIndex, int destIndex, FindPath pathType = FindPath::Fast);
|
||||
void clearRoute ();
|
||||
void debugMsgInternal (const char *str);
|
||||
|
|
@ -823,6 +861,7 @@ private:
|
|||
void selectSecondary ();
|
||||
void selectWeaponByName (const char *name);
|
||||
void selectWeaponById (int num);
|
||||
|
||||
void completeTask ();
|
||||
void executeTasks ();
|
||||
void trackEnemies ();
|
||||
|
|
@ -992,7 +1031,7 @@ public:
|
|||
void newRound ();
|
||||
void enteredBuyZone (int buyState);
|
||||
void pushMsgQueue (int message);
|
||||
void prepareChatMessage (const String &message);
|
||||
void prepareChatMessage (StringRef message);
|
||||
void checkForChat ();
|
||||
void showChaterIcon (bool show);
|
||||
void clearSearchNodes ();
|
||||
|
|
@ -1003,8 +1042,7 @@ public:
|
|||
void filterTasks ();
|
||||
void clearTasks ();
|
||||
void dropWeaponForUser (edict_t *user, bool discardC4);
|
||||
void say (const char *text);
|
||||
void sayTeam (const char *text);
|
||||
void sendToChat (StringRef message, bool teamOnly);
|
||||
void pushChatMessage (int type, bool isTeamSay = false);
|
||||
void pushRadioMessage (int message);
|
||||
void pushChatterMessage (int message);
|
||||
|
|
@ -1028,6 +1066,7 @@ public:
|
|||
bool isShieldDrawn ();
|
||||
bool findBestNearestNode ();
|
||||
bool seesEntity (const Vector &dest, bool fromBody = false);
|
||||
bool canSkipNextTrace (TraceChannel channel);
|
||||
|
||||
int getAmmo ();
|
||||
int getNearestToPlantedBomb ();
|
||||
|
|
@ -1066,32 +1105,44 @@ public:
|
|||
return m_index + 1;
|
||||
}
|
||||
|
||||
// set the last bot trace result
|
||||
void setLastTraceResult (TraceChannel channel, TraceResult *traceResult) {
|
||||
m_lastTrace[channel] = *traceResult;
|
||||
}
|
||||
|
||||
// get the bot last trace result
|
||||
TraceResult *getLastTraceResult (TraceChannel channel) {
|
||||
return &m_lastTrace[channel];
|
||||
}
|
||||
|
||||
// prints debug message
|
||||
template <typename ...Args> void debugMsg (const char *fmt, Args ...args) {
|
||||
template <typename ...Args> void debugMsg (const char *fmt, Args &&...args) {
|
||||
debugMsgInternal (strings.format (fmt, cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
// execute client command helper
|
||||
template <typename ...Args> void issueCommand (const char *fmt, Args ...args);
|
||||
template <typename ...Args> void issueCommand (const char *fmt, Args &&...args);
|
||||
};
|
||||
|
||||
#include <config.h>
|
||||
#include <utils.h>
|
||||
#include <support.h>
|
||||
#include <message.h>
|
||||
#include <engine.h>
|
||||
#include <manager.h>
|
||||
#include <control.h>
|
||||
|
||||
// very global convars
|
||||
extern ConVar yb_jasonmode;
|
||||
extern ConVar yb_radio_mode;
|
||||
extern ConVar yb_ignore_enemies;
|
||||
extern ConVar yb_chat;
|
||||
extern ConVar yb_language;
|
||||
extern ConVar yb_show_latency;
|
||||
extern ConVar yb_enable_query_hook;
|
||||
extern ConVar cv_jasonmode;
|
||||
extern ConVar cv_radio_mode;
|
||||
extern ConVar cv_ignore_enemies;
|
||||
extern ConVar cv_chat;
|
||||
extern ConVar cv_language;
|
||||
extern ConVar cv_show_latency;
|
||||
extern ConVar cv_enable_query_hook;
|
||||
extern ConVar cv_whose_your_daddy;
|
||||
extern ConVar cv_chatter_path;
|
||||
|
||||
// execute client command helper
|
||||
template <typename ...Args> void Bot::issueCommand (const char * fmt, Args ...args) {
|
||||
template <typename ...Args> void Bot::issueCommand (const char *fmt, Args &&...args) {
|
||||
game.botCommand (ent (), strings.format (fmt, cr::forward <Args> (args)...));
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
#include <crlib/cr-platform.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// default allocator for cr-objects
|
||||
class Allocator : public Singleton <Allocator> {
|
||||
public:
|
||||
Allocator () = default;
|
||||
~Allocator () = default;
|
||||
|
||||
public:
|
||||
template <typename T> T *allocate (const size_t length = 1) {
|
||||
auto ptr = reinterpret_cast <T *> (calloc (length, sizeof (T)));
|
||||
|
||||
if (!ptr) {
|
||||
plat.abort ();
|
||||
}
|
||||
|
||||
// calloc on linux with debug enabled doesn't always zero out memory
|
||||
#if defined (CR_DEBUG) && !defined (CR_WINDOWS)
|
||||
plat.bzero (ptr, length);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T> void deallocate (T *ptr) {
|
||||
if (ptr) {
|
||||
free (reinterpret_cast <T *> (ptr));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> void construct (T *d, Args &&...args) {
|
||||
new (d) T (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
template <typename T> void destruct (T *d) {
|
||||
d->~T ();
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T, typename ...Args> T *create (Args &&...args) {
|
||||
auto d = allocate <T> ();
|
||||
new (d) T (cr::forward <Args> (args)...);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename T> void destroy (T *ptr) {
|
||||
if (ptr) {
|
||||
destruct (ptr);
|
||||
deallocate (ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CR_EXPOSE_GLOBAL_SINGLETON (Allocator, alloc);
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple color holder
|
||||
class Color final {
|
||||
public:
|
||||
int32 red = 0, green = 0, blue = 0;
|
||||
|
||||
public:
|
||||
explicit Color (int32 r, int32 g, int32 b) : red (r), green (g), blue (b) { }
|
||||
|
||||
Color () = default;
|
||||
~Color () = default;
|
||||
|
||||
public:
|
||||
void reset () {
|
||||
red = green = blue = 0;
|
||||
}
|
||||
|
||||
int32 avg () const {
|
||||
return sum () / (sizeof (Color) / sizeof (int32));
|
||||
}
|
||||
|
||||
int32 sum () const {
|
||||
return red + green + blue;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,349 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <crlib/cr-string.h>
|
||||
#include <crlib/cr-lambda.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple stdio file wrapper
|
||||
class File final : private DenyCopying {
|
||||
private:
|
||||
FILE *m_handle = nullptr;
|
||||
size_t m_length = 0;
|
||||
|
||||
public:
|
||||
explicit File () = default;
|
||||
|
||||
File (const String &file, const String &mode = "rt") {
|
||||
open (file, mode);
|
||||
}
|
||||
|
||||
~File () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (const String &file, const String &mode) {
|
||||
if (!openFile (file, mode)) {
|
||||
return false;
|
||||
}
|
||||
fseek (m_handle, 0L, SEEK_END);
|
||||
m_length = ftell (m_handle);
|
||||
fseek (m_handle, 0L, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
if (m_handle != nullptr) {
|
||||
fclose (m_handle);
|
||||
m_handle = nullptr;
|
||||
}
|
||||
m_length = 0;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return !!feof (m_handle);
|
||||
}
|
||||
|
||||
bool flush () const {
|
||||
return !!fflush (m_handle);
|
||||
}
|
||||
|
||||
int getChar () const {
|
||||
return fgetc (m_handle);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, int count) const {
|
||||
return fgets (buffer, count, m_handle);
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
line.clear ();
|
||||
int ch;
|
||||
|
||||
while ((ch = getChar ()) != EOF && !eof ()) {
|
||||
line += static_cast <char> (ch);
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !eof ();
|
||||
}
|
||||
|
||||
template <typename ...Args> size_t puts (const char *fmt, Args ...args) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return fprintf (m_handle, fmt, cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
bool puts (const char *buffer) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
if (fputs (buffer, m_handle) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int putChar (int ch) {
|
||||
return fputc (ch, m_handle);
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
return fread (buffer, size, count, m_handle);
|
||||
}
|
||||
|
||||
size_t write (void *buffer, size_t size, size_t count = 1) {
|
||||
return fwrite (buffer, size, count, m_handle);
|
||||
}
|
||||
|
||||
bool seek (long offset, int origin) {
|
||||
if (fseek (m_handle, offset, origin) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
::rewind (m_handle);
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
static inline bool exists (const String &file) {
|
||||
File fp;
|
||||
|
||||
if (fp.open (file, "rb")) {
|
||||
fp.close ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void createPath (const char *path) {
|
||||
for (auto str = const_cast <char *> (path) + 1; *str; ++str) {
|
||||
if (*str == '/') {
|
||||
*str = 0;
|
||||
plat.createDirectory (path);
|
||||
*str = '/';
|
||||
}
|
||||
}
|
||||
plat.createDirectory (path);
|
||||
}
|
||||
|
||||
private:
|
||||
bool openFile (const String &filename, const String &mode) {
|
||||
if (*this) {
|
||||
close ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
fopen_s (&m_handle, filename.chars (), mode.chars ());
|
||||
#else
|
||||
m_handle = fopen (filename.chars (), mode.chars ());
|
||||
#endif
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// wrapper for memory file for loading data into the memory
|
||||
class MemFileStorage : public Singleton <MemFileStorage> {
|
||||
private:
|
||||
using LoadFunction = Lambda <uint8 * (const char *, int *)>;
|
||||
using FreeFunction = Lambda <void (void *)>;
|
||||
|
||||
private:
|
||||
LoadFunction m_load = nullptr;
|
||||
FreeFunction m_free = nullptr;
|
||||
|
||||
public:
|
||||
inline MemFileStorage () = default;
|
||||
inline ~MemFileStorage () = default;
|
||||
|
||||
public:
|
||||
void initizalize (LoadFunction loader, FreeFunction unloader) {
|
||||
m_load = cr::move (loader);
|
||||
m_free = cr::move (unloader);
|
||||
}
|
||||
|
||||
public:
|
||||
uint8 *load (const String &file, int *size) {
|
||||
if (m_load) {
|
||||
return m_load (file.chars (), size);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void unload (void *buffer) {
|
||||
if (m_free) {
|
||||
m_free (buffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MemFile final : public DenyCopying {
|
||||
private:
|
||||
enum : char {
|
||||
Eof = static_cast <char> (-1)
|
||||
};
|
||||
|
||||
private:
|
||||
uint8 *m_data = nullptr;
|
||||
size_t m_length = 0, m_pos = 0;
|
||||
|
||||
public:
|
||||
explicit MemFile () = default;
|
||||
|
||||
MemFile (const String &file) {
|
||||
open (file);
|
||||
}
|
||||
|
||||
~MemFile () {
|
||||
close ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool open (const String &file) {
|
||||
m_length = 0;
|
||||
m_pos = 0;
|
||||
m_data = MemFileStorage::get ().load (file.chars (), reinterpret_cast <int *> (&m_length));
|
||||
|
||||
if (!m_data) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void close () {
|
||||
MemFileStorage::get ().unload (m_data);
|
||||
|
||||
m_length = 0;
|
||||
m_pos = 0;
|
||||
m_data = nullptr;
|
||||
}
|
||||
|
||||
char getChar () {
|
||||
if (!m_data || m_pos >= m_length) {
|
||||
return Eof;
|
||||
}
|
||||
auto ch = m_data[m_pos];
|
||||
++m_pos;
|
||||
|
||||
return static_cast <char> (ch);
|
||||
}
|
||||
|
||||
char *getString (char *buffer, size_t count) {
|
||||
if (!m_data || m_pos >= m_length) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t index = 0;
|
||||
buffer[0] = 0;
|
||||
|
||||
for (; index < count - 1;) {
|
||||
if (m_pos < m_length) {
|
||||
buffer[index] = m_data[m_pos++];
|
||||
|
||||
if (buffer[index++] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[index] = 0;
|
||||
return index ? buffer : nullptr;
|
||||
}
|
||||
|
||||
bool getLine (String &line) {
|
||||
line.clear ();
|
||||
char ch;
|
||||
|
||||
while ((ch = getChar ()) != Eof) {
|
||||
line += ch;
|
||||
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return !eof ();
|
||||
}
|
||||
|
||||
size_t read (void *buffer, size_t size, size_t count = 1) {
|
||||
if (!m_data || m_length <= m_pos || !buffer || !size || !count) {
|
||||
return 0;
|
||||
}
|
||||
size_t blocks_read = size * count <= m_length - m_pos ? size * count : m_length - m_pos;
|
||||
|
||||
memcpy (buffer, &m_data[m_pos], blocks_read);
|
||||
m_pos += blocks_read;
|
||||
|
||||
return blocks_read / size;
|
||||
}
|
||||
|
||||
bool seek (size_t offset, int origin) {
|
||||
if (!m_data || m_pos >= m_length) {
|
||||
return false;
|
||||
}
|
||||
if (origin == SEEK_SET) {
|
||||
if (offset >= m_length) {
|
||||
return false;
|
||||
}
|
||||
m_pos = offset;
|
||||
}
|
||||
else if (origin == SEEK_END) {
|
||||
if (offset >= m_length) {
|
||||
return false;
|
||||
}
|
||||
m_pos = m_length - offset;
|
||||
}
|
||||
else {
|
||||
if (m_pos + offset >= m_length) {
|
||||
return false;
|
||||
}
|
||||
m_pos += offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t length () const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
bool eof () const {
|
||||
return m_pos >= m_length;
|
||||
}
|
||||
|
||||
void rewind () {
|
||||
m_pos = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return !!m_data && m_length > 0;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
class SimpleHook : DenyCopying {
|
||||
private:
|
||||
enum : uint32 {
|
||||
#if defined (CR_ARCH_X64)
|
||||
CodeLength = 14
|
||||
#else
|
||||
CodeLength = 6
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined (CR_ARCH_X64)
|
||||
using uint = uint64;
|
||||
#else
|
||||
using uint = uint32;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_patched;
|
||||
|
||||
uint m_pageSize;
|
||||
uint m_origFunc;
|
||||
uint m_hookFunc;
|
||||
|
||||
uint8 m_origBytes[CodeLength] {};
|
||||
uint8 m_hookBytes[CodeLength] {};
|
||||
|
||||
private:
|
||||
void setPageSize () {
|
||||
#if defined (CR_WINDOWS)
|
||||
SYSTEM_INFO sysinfo;
|
||||
GetSystemInfo (&sysinfo);
|
||||
|
||||
m_pageSize = sysinfo.dwPageSize;
|
||||
#else
|
||||
m_pageSize = sysconf (_SC_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined (CR_WINDOWS)
|
||||
void *align (void *address) {
|
||||
return reinterpret_cast <void *> ((reinterpret_cast <long> (address) & ~(m_pageSize - 1)));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool unprotect () {
|
||||
auto orig = reinterpret_cast <void *> (m_origFunc);
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
DWORD oldProt;
|
||||
|
||||
FlushInstructionCache (GetCurrentProcess (), orig, CodeLength);
|
||||
return VirtualProtect (orig, CodeLength, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
#else
|
||||
auto aligned = align (orig);
|
||||
return !mprotect (aligned, m_pageSize, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
SimpleHook () : m_patched (false), m_pageSize (0), m_origFunc (0), m_hookFunc (0) {
|
||||
setPageSize ();
|
||||
}
|
||||
|
||||
~SimpleHook () {
|
||||
disable ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool patch (void *address, void *replacement) {
|
||||
const uint16 jmp = 0x25ff;
|
||||
|
||||
if (plat.arm) {
|
||||
return false;
|
||||
}
|
||||
auto ptr = reinterpret_cast <uint8 *> (address);
|
||||
|
||||
while (*reinterpret_cast <uint16 *> (ptr) == jmp) {
|
||||
ptr = **reinterpret_cast <uint8 * **> (ptr + 2);
|
||||
}
|
||||
m_origFunc = reinterpret_cast <uint> (address);
|
||||
|
||||
if (!m_origFunc) {
|
||||
return false;
|
||||
}
|
||||
m_hookFunc = reinterpret_cast <uint> (replacement);
|
||||
|
||||
if (plat.x64) {
|
||||
const uint16 nop = 0x00000000;
|
||||
|
||||
memcpy (&m_hookBytes[0], &jmp, sizeof (uint16));
|
||||
memcpy (&m_hookBytes[2], &nop, sizeof (uint16));
|
||||
memcpy (&m_hookBytes[6], &replacement, sizeof (uint));
|
||||
}
|
||||
else {
|
||||
m_hookBytes[0] = 0x68;
|
||||
m_hookBytes[5] = 0xc3;
|
||||
|
||||
memcpy (&m_hookBytes[1], &m_hookFunc, sizeof (uint));
|
||||
}
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (m_origBytes, reinterpret_cast <void *> (m_origFunc), CodeLength);
|
||||
return enable ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enable () {
|
||||
if (m_patched) {
|
||||
return false;
|
||||
}
|
||||
m_patched = true;
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (reinterpret_cast <void *> (m_origFunc), m_hookBytes, CodeLength);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool disable () {
|
||||
if (!m_patched) {
|
||||
return false;
|
||||
}
|
||||
m_patched = false;
|
||||
|
||||
if (unprotect ()) {
|
||||
memcpy (reinterpret_cast <void *> (m_origFunc), m_origBytes, CodeLength);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool enabled () const {
|
||||
return m_patched;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-alloc.h>
|
||||
#include <crlib/cr-uniqueptr.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
template <typename> class Lambda;
|
||||
template <typename R, typename ...Args> class Lambda <R (Args...)> {
|
||||
private:
|
||||
enum : uint32 {
|
||||
LamdaSmallBufferLength = sizeof (void *) * 16
|
||||
};
|
||||
|
||||
private:
|
||||
class LambdaFunctorWrapper {
|
||||
public:
|
||||
LambdaFunctorWrapper () = default;
|
||||
virtual ~LambdaFunctorWrapper () = default;
|
||||
|
||||
public:
|
||||
virtual void move (uint8 *to) = 0;
|
||||
virtual void small (uint8 *to) const = 0;
|
||||
|
||||
virtual R invoke (Args &&...) = 0;
|
||||
virtual UniquePtr <LambdaFunctorWrapper> clone () const = 0;
|
||||
|
||||
public:
|
||||
void operator delete (void *ptr) {
|
||||
alloc.deallocate (ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> class LambdaFunctor : public LambdaFunctorWrapper {
|
||||
private:
|
||||
T m_callable;
|
||||
|
||||
public:
|
||||
LambdaFunctor (const T &callable) : LambdaFunctorWrapper (), m_callable (callable)
|
||||
{ }
|
||||
|
||||
LambdaFunctor (T &&callable) : LambdaFunctorWrapper (), m_callable (cr::move (callable))
|
||||
{ }
|
||||
|
||||
~LambdaFunctor () override = default;
|
||||
|
||||
public:
|
||||
void move (uint8 *to) override {
|
||||
new (to) LambdaFunctor<T> (cr::move (m_callable));
|
||||
}
|
||||
|
||||
void small (uint8 *to) const override {
|
||||
new (to) LambdaFunctor<T> (m_callable);
|
||||
}
|
||||
|
||||
R invoke (Args &&... args) override {
|
||||
return m_callable (cr::forward <Args> (args)...);
|
||||
}
|
||||
|
||||
UniquePtr <LambdaFunctorWrapper> clone () const override {
|
||||
return makeUnique <LambdaFunctor <T>> (m_callable);
|
||||
}
|
||||
};
|
||||
|
||||
union {
|
||||
UniquePtr <LambdaFunctorWrapper> m_functor;
|
||||
uint8 m_small[LamdaSmallBufferLength];
|
||||
};
|
||||
|
||||
bool m_smallObject;
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
if (m_smallObject) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (m_small)->~LambdaFunctorWrapper ();
|
||||
}
|
||||
else {
|
||||
m_functor.reset ();
|
||||
}
|
||||
}
|
||||
|
||||
void swap (Lambda &rhs) noexcept {
|
||||
cr::swap (rhs, *this);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Lambda () noexcept : Lambda (nullptr)
|
||||
{ }
|
||||
|
||||
Lambda (decltype (nullptr)) noexcept : m_functor (nullptr), m_smallObject (false)
|
||||
{ }
|
||||
|
||||
Lambda (const Lambda &rhs) {
|
||||
if (rhs.m_smallObject) {
|
||||
reinterpret_cast <const LambdaFunctorWrapper *> (rhs.m_small)->small (m_small);
|
||||
}
|
||||
else {
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (rhs.m_functor->clone ());
|
||||
}
|
||||
m_smallObject = rhs.m_smallObject;
|
||||
}
|
||||
|
||||
Lambda (Lambda &&rhs) noexcept {
|
||||
if (rhs.m_smallObject) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.m_small)->move (m_small);
|
||||
new (rhs.m_small) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.m_functor));
|
||||
}
|
||||
m_smallObject = rhs.m_smallObject;
|
||||
rhs.m_smallObject = false;
|
||||
}
|
||||
|
||||
template <typename F> Lambda (F function) {
|
||||
if (cr::fix (sizeof (function) > LamdaSmallBufferLength)) {
|
||||
m_smallObject = false;
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (makeUnique <LambdaFunctor <F>> (cr::move (function)));
|
||||
}
|
||||
else {
|
||||
m_smallObject = true;
|
||||
new (m_small) LambdaFunctor<F> (cr::move (function));
|
||||
}
|
||||
}
|
||||
|
||||
~Lambda () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
Lambda &operator = (const Lambda &rhs) {
|
||||
destroy ();
|
||||
|
||||
Lambda tmp (rhs);
|
||||
swap (tmp);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Lambda &operator = (Lambda &&rhs) noexcept {
|
||||
destroy ();
|
||||
|
||||
if (rhs.m_smallObject) {
|
||||
reinterpret_cast <LambdaFunctorWrapper *> (rhs.m_small)->move (m_small);
|
||||
new (rhs.m_small) UniquePtr <LambdaFunctorWrapper> (nullptr);
|
||||
}
|
||||
else {
|
||||
new (m_small) UniquePtr <LambdaFunctorWrapper> (cr::move (rhs.m_functor));
|
||||
}
|
||||
|
||||
m_smallObject = rhs.m_smallObject;
|
||||
rhs.m_smallObject = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool () const noexcept {
|
||||
return m_smallObject || !!m_functor;
|
||||
}
|
||||
|
||||
public:
|
||||
R operator () (Args ...args) {
|
||||
return m_smallObject ? reinterpret_cast <LambdaFunctorWrapper *> (m_small)->invoke (cr::forward <Args> (args)...) : m_functor->invoke (cr::forward <Args> (args)...);
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-string.h>
|
||||
|
||||
#if defined (CR_LINUX) || defined (CR_OSX)
|
||||
# include <dlfcn.h>
|
||||
# include <errno.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// handling dynamic library loading
|
||||
class SharedLibrary final : public DenyCopying {
|
||||
private:
|
||||
void *m_handle = nullptr;
|
||||
|
||||
public:
|
||||
explicit SharedLibrary () = default;
|
||||
|
||||
SharedLibrary (const String &file) {
|
||||
if (file.empty ()) {
|
||||
return;
|
||||
}
|
||||
load (file);
|
||||
}
|
||||
|
||||
~SharedLibrary () {
|
||||
unload ();
|
||||
}
|
||||
|
||||
public:
|
||||
bool load (const String &file) noexcept {
|
||||
if (*this) {
|
||||
unload ();
|
||||
}
|
||||
|
||||
#if defined (CR_WINDOWS)
|
||||
m_handle = LoadLibraryA (file.chars ());
|
||||
#else
|
||||
m_handle = dlopen (file.chars (), RTLD_NOW);
|
||||
#endif
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
|
||||
bool locate (void *address) {
|
||||
#if defined (CR_WINDOWS)
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
|
||||
if (!VirtualQuery (address, &mbi, sizeof (mbi))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mbi.State != MEM_COMMIT) {
|
||||
return false;
|
||||
}
|
||||
m_handle = reinterpret_cast <void *> (mbi.AllocationBase);
|
||||
#else
|
||||
Dl_info dli;
|
||||
plat.bzero (&dli, sizeof (dli));
|
||||
|
||||
if (dladdr (address, &dli)) {
|
||||
return load (dli.dli_fname);
|
||||
}
|
||||
#endif
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
|
||||
void unload () noexcept {
|
||||
if (!*this) {
|
||||
return;
|
||||
}
|
||||
#if defined (CR_WINDOWS)
|
||||
FreeLibrary (static_cast <HMODULE> (m_handle));
|
||||
#else
|
||||
dlclose (m_handle);
|
||||
#endif
|
||||
m_handle = nullptr;
|
||||
}
|
||||
|
||||
template <typename R> R resolve (const char *function) const {
|
||||
if (!*this) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast <R> (
|
||||
#if defined (CR_WINDOWS)
|
||||
GetProcAddress (static_cast <HMODULE> (m_handle), function)
|
||||
#else
|
||||
dlsym (m_handle, function)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void *handle () const {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit operator bool () const {
|
||||
return m_handle != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <crlib/cr-basic.h>
|
||||
#include <crlib/cr-movable.h>
|
||||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// simple unique ptr
|
||||
template <typename T> class UniquePtr final : public DenyCopying {
|
||||
private:
|
||||
T *m_ptr = nullptr;
|
||||
|
||||
public:
|
||||
UniquePtr () = default;
|
||||
|
||||
explicit UniquePtr (T *ptr) : m_ptr (ptr)
|
||||
{ }
|
||||
|
||||
UniquePtr (UniquePtr &&rhs) noexcept : m_ptr (rhs.release ())
|
||||
{ }
|
||||
|
||||
template <typename U> UniquePtr (UniquePtr <U> &&rhs) noexcept : m_ptr (rhs.release ())
|
||||
{ }
|
||||
|
||||
~UniquePtr () {
|
||||
destroy ();
|
||||
}
|
||||
|
||||
public:
|
||||
T *get () const {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
T *release () {
|
||||
auto ret = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset (T *ptr = nullptr) {
|
||||
destroy ();
|
||||
m_ptr = ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void destroy () {
|
||||
if (m_ptr) {
|
||||
alloc.destroy (m_ptr);
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
UniquePtr &operator = (UniquePtr &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U> UniquePtr &operator = (UniquePtr <U> &&rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
reset (rhs.release ());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
UniquePtr &operator = (decltype (nullptr)) {
|
||||
destroy ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator * () const {
|
||||
return *m_ptr;
|
||||
}
|
||||
|
||||
T *operator -> () const {
|
||||
return m_ptr;
|
||||
}
|
||||
|
||||
explicit operator bool () const {
|
||||
return m_ptr != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// create unique
|
||||
template <typename T, typename... Args> UniquePtr <T> makeUnique (Args &&... args) {
|
||||
return UniquePtr <T> (alloc.create <T> (cr::forward <Args> (args)...));
|
||||
}
|
||||
|
||||
CR_NAMESPACE_END
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// general product information
|
||||
#define PRODUCT_NAME "Yet Another POD-Bot"
|
||||
#define PRODUCT_SHORT_NAME "YaPB"
|
||||
#define PRODUCT_VERSION "2.92"
|
||||
#define PRODUCT_AUTHOR "YaPB Contributors"
|
||||
#define PRODUCT_URL "https://yapb.ru/"
|
||||
#define PRODUCT_EMAIL "yapb@entix.io"
|
||||
#define PRODUCT_LOGTAG "YAPB"
|
||||
#define PRODUCT_END_YEAR "2020"
|
||||
#define PRODUCT_DESCRIPTION PRODUCT_NAME " v" PRODUCT_VERSION " - The Counter-Strike Bot (" PRODUCT_COMMENTS ")"
|
||||
#define PRODUCT_COPYRIGHT "Copyright © 2004-" PRODUCT_END_YEAR ", by " PRODUCT_AUTHOR
|
||||
#define PRODUCT_LEGAL "Half-Life, Counter-Strike, Counter-Strike: Condition Zero, Steam, Valve is a trademark of Valve Corporation"
|
||||
#define PRODUCT_ORIGINAL_NAME "yapb.dll"
|
||||
#define PRODUCT_INTERNAL_NAME "podbot"
|
||||
#define PRODUCT_GIT_HASH "unspecified_hash"
|
||||
#define PRODUCT_GIT_COMMIT_AUTHOR "unspecified_author"
|
||||
#define PRODUCT_GIT_COMMIT_ID 0000
|
||||
#define PRODUCT_VERSION_DWORD_INTERNAL 2,92
|
||||
#define PRODUCT_VERSION_DWORD PRODUCT_VERSION_DWORD_INTERNAL, PRODUCT_GIT_COMMIT_ID
|
||||
#define PRODUCT_SUPPORT_VERSION "Beta 6.6 - Condition Zero"
|
||||
#define PRODUCT_COMMENTS "http://github.com/jeefo/yapb/"
|
||||
#define PRODUCT_DATE __DATE__
|
||||
|
||||
252
meson.build
Normal file
252
meson.build
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
#
|
||||
# YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
# Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
|
||||
project (
|
||||
'yapb',
|
||||
'cpp',
|
||||
|
||||
version: '4.0.0',
|
||||
license: 'GPL',
|
||||
|
||||
default_options: [
|
||||
'buildtype=release',
|
||||
'b_ndebug=if-release',
|
||||
'cpp_std=c++14',
|
||||
'warning_level=3',
|
||||
'werror=true',
|
||||
'backend=ninja',
|
||||
'strip=true',
|
||||
'optimization=3',
|
||||
'default_library=static',
|
||||
'cpp_eh=none'
|
||||
],
|
||||
meson_version: '>=0.48.0')
|
||||
|
||||
find_program ('ninja', required: true)
|
||||
find_program ('git', required: true)
|
||||
find_program ('hostname', required: true)
|
||||
|
||||
buildCompiler = meson.get_compiler ('cpp')
|
||||
buildSystem = host_machine.system ()
|
||||
buildVersion = meson.project_version ()
|
||||
|
||||
compilerId = buildCompiler.get_id ()
|
||||
compilerVersion = buildCompiler.version ()
|
||||
|
||||
isOptimize = get_option ('buildtype') == 'release'
|
||||
isVC = compilerId == 'msvc' or compilerId == 'intel-cl' or compilerId == 'clang-cl'
|
||||
isGCC = compilerId == 'gcc'
|
||||
isIntel = compilerId == 'intel' or compilerId == 'intel-cl'
|
||||
isCLang = compilerId == 'clang'
|
||||
isWindows = buildSystem == 'windows'
|
||||
isLinux = buildSystem == 'linux'
|
||||
isDarwin = buildSystem == 'darwin'
|
||||
|
||||
flagsLinker = []
|
||||
flagsCompiler = []
|
||||
|
||||
cdata = configuration_data()
|
||||
|
||||
if isWindows
|
||||
cdata.set ('buildVersionWin', ','.join (buildVersion.split ('.')))
|
||||
else
|
||||
cdata.set ('buildVersionWin', buildVersion)
|
||||
endif
|
||||
|
||||
cdata.set ('commitHash', run_command ('git', 'rev-parse', '--short', 'HEAD').stdout ().strip ())
|
||||
cdata.set ('commitCount', run_command ('git', 'rev-list', '--count', 'HEAD').stdout ().strip ())
|
||||
cdata.set ('commitAuthor', run_command ('git', 'log', '--pretty="%ae"', '-1').stdout ().strip ())
|
||||
|
||||
cdata.set ('buildVersion', buildVersion)
|
||||
cdata.set ('buildMachine', run_command ('hostname').stdout ().strip ())
|
||||
cdata.set ('buildCompiler', compilerId + ' ' + compilerVersion)
|
||||
|
||||
configure_file (input: 'inc/version.h.in', output: 'version.build.h', configuration: cdata)
|
||||
|
||||
flagsCompiler += '-DVERSION_GENERATED'
|
||||
|
||||
if isCLang or isGCC or (isIntel and not isWindows)
|
||||
flagsCompiler += [
|
||||
'-m32',
|
||||
'-fno-threadsafe-statics',
|
||||
'-fno-exceptions',
|
||||
'-fno-rtti',
|
||||
]
|
||||
|
||||
if isOptimize
|
||||
flagsCompiler += '-msse3'
|
||||
|
||||
if (isCLang or isGCC) and not isDarwin
|
||||
flagsCompiler += '-flto'
|
||||
flagsLinker += '-flto'
|
||||
|
||||
if isGCC
|
||||
flagsCompiler += [
|
||||
'-fgraphite-identity'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if isLinux
|
||||
flagsLinker += [
|
||||
'-m32',
|
||||
'-lm',
|
||||
'-ldl'
|
||||
]
|
||||
endif
|
||||
endif
|
||||
|
||||
if isIntel and (isLinux or isDarwin)
|
||||
flagsLinker += [
|
||||
'-static-intel',
|
||||
'-no-intel-extensions'
|
||||
]
|
||||
endif
|
||||
|
||||
if isLinux or isDarwin
|
||||
if isDarwin
|
||||
flagsCompiler += '-mmacosx-version-min=10.9'
|
||||
flagsLinker += [
|
||||
'-dynamiclib',
|
||||
'-lstdc++',
|
||||
'-mmacosx-version-min=10.9'
|
||||
]
|
||||
else
|
||||
flagsLinker += '-static-libgcc'
|
||||
endif
|
||||
|
||||
if not isOptimize
|
||||
flagsCompiler += [
|
||||
'-g3',
|
||||
'-ggdb',
|
||||
'-O3',
|
||||
'-DCR_DEBUG'
|
||||
]
|
||||
else
|
||||
flagsCompiler += [
|
||||
'-mtune=generic',
|
||||
'-msse3',
|
||||
'-mfpmath=sse',
|
||||
'-fno-builtin',
|
||||
'-funroll-loops',
|
||||
'-fomit-frame-pointer',
|
||||
'-fno-stack-protector',
|
||||
'-fvisibility=hidden',
|
||||
'-fvisibility-inlines-hidden'
|
||||
]
|
||||
|
||||
if isIntel
|
||||
flagsCompiler += [
|
||||
'-funroll-all-loops',
|
||||
'-ipo',
|
||||
'-wd11076',
|
||||
'-wd11074'
|
||||
]
|
||||
|
||||
flagsLinker += [
|
||||
'-cxxlib-nostd',
|
||||
'-Wl,--no-undefined,-z,notext,--gc-sections',
|
||||
'-ipo'
|
||||
]
|
||||
elif isCLang and not isDarwin
|
||||
llvmLinker = find_program ('lld', required: false)
|
||||
|
||||
if llvmLinker.found() == true
|
||||
flagsLinker += '-fuse-ld=' + llvmLinker.path ().split ('/')[-1]
|
||||
endif
|
||||
|
||||
flagsLinker += [
|
||||
'-nostdlib++',
|
||||
'-Wunused-command-line-argument',
|
||||
'-Wl,-z,notext',
|
||||
'--no-undefined'
|
||||
]
|
||||
elif isGCC and not isDarwin
|
||||
flagsCompiler += '-funroll-all-loops'
|
||||
flagsLinker += '-Wl,--no-undefined'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if isWindows and (isVC or isIntel)
|
||||
flagsLinker += [
|
||||
'/MACHINE:X86',
|
||||
'user32.lib',
|
||||
'ws2_32.lib'
|
||||
]
|
||||
|
||||
flagsCompiler += [
|
||||
'/TP'
|
||||
]
|
||||
|
||||
if isOptimize
|
||||
flagsCompiler += '/GL'
|
||||
flagsLinker += '/LTCG'
|
||||
endif
|
||||
|
||||
elif isWindows and (isCLang or isGCC)
|
||||
if isCLang
|
||||
flagsLinker += '-Wl,/MACHINE:X86'
|
||||
else
|
||||
flagsLinker += [
|
||||
'-static-libgcc',
|
||||
'-Wl,--add-stdcall-alias'
|
||||
]
|
||||
endif
|
||||
|
||||
flagsLinker += [
|
||||
'-luser32',
|
||||
'-lws2_32'
|
||||
]
|
||||
endif
|
||||
|
||||
add_global_arguments (flagsCompiler, language: 'cpp')
|
||||
add_global_link_arguments (flagsLinker, language: 'cpp')
|
||||
|
||||
sourceFiles = files (
|
||||
'src/android.cpp',
|
||||
'src/botlib.cpp',
|
||||
'src/chatlib.cpp',
|
||||
'src/combat.cpp',
|
||||
'src/control.cpp',
|
||||
'src/engine.cpp',
|
||||
'src/graph.cpp',
|
||||
'src/linkage.cpp',
|
||||
'src/manager.cpp',
|
||||
'src/message.cpp',
|
||||
'src/navigate.cpp',
|
||||
'src/support.cpp'
|
||||
)
|
||||
|
||||
includes = include_directories ([
|
||||
'.', 'inc', 'ext',
|
||||
], is_system: true)
|
||||
|
||||
if isWindows and not isCLang
|
||||
sourceFiles += import('windows').compile_resources (
|
||||
'vc/yapb.rc',
|
||||
include_directories: includes,
|
||||
args: '-DVERSION_GENERATED'
|
||||
)
|
||||
endif
|
||||
|
||||
shared_library (
|
||||
'yapb',
|
||||
sourceFiles,
|
||||
include_directories: includes,
|
||||
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
name_prefix: '')
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
#
|
||||
# Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
# Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
#
|
||||
# This software is licensed under the MIT license.
|
||||
# Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
#
|
||||
|
||||
PROJECT = yapb
|
||||
SOURCES = ../source
|
||||
OBJECTS = $(wildcard $(SOURCES)/*.cpp)
|
||||
|
||||
COMPILER_FLAGS = -std=c++11 -m32 -Wall -Wextra -Werror -fno-exceptions -fno-rtti -pedantic
|
||||
LINKER_FLAGS = -m32 -ldl
|
||||
|
||||
ifeq "$(DEBUG)" "true"
|
||||
COMPILER_FLAGS += -g3 -DCR_DEBUG
|
||||
BINARY_DIR = debug
|
||||
else
|
||||
COMPILER_FLAGS += -pipe -O3 -march=core2 -msse2 -mfpmath=sse -fno-builtin -fno-threadsafe-statics -funroll-loops -fomit-frame-pointer -fno-stack-protector -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
BINARY_DIR = release
|
||||
endif
|
||||
|
||||
INCLUDE = -I../include
|
||||
COMPILER = $(CC)
|
||||
|
||||
ifeq "$(shell uname -s)" "Darwin"
|
||||
OSX = true
|
||||
endif
|
||||
|
||||
ifeq "$(OSX)" "true"
|
||||
LIBRARY_EXT = dylib
|
||||
COMPILER_FLAGS += -mmacosx-version-min=10.9
|
||||
LINKER_FLAGS += -dynamiclib -lstdc++ -mmacosx-version-min=10.9 -arch i386
|
||||
else
|
||||
LIBRARY_EXT = so
|
||||
LINKER_FLAGS += -shared -static-libgcc
|
||||
endif
|
||||
|
||||
BINARY_OUTPUT = $(PROJECT).$(LIBRARY_EXT)
|
||||
|
||||
ifeq ($(findstring clang,$(COMPILER)),clang)
|
||||
ifneq "$(OSX)" "true"
|
||||
ifeq "$(DEBUG)" "true"
|
||||
LINKER_FLAGS += -lstdc++
|
||||
else
|
||||
LINKER_FLAGS += -nostdlib++ -Wunused-command-line-argument -fuse-ld=lld -Wl,-z,notext --no-undefined
|
||||
endif
|
||||
endif
|
||||
else ifeq ($(findstring gcc,$(COMPILER)),gcc)
|
||||
ifneq "$(OSX)" "true"
|
||||
ifneq "$(DEBUG)" "true"
|
||||
LINKER_FLAGS += -Wl,--no-undefined
|
||||
COMPILER_FLAGS += -funroll-all-loops
|
||||
endif
|
||||
endif
|
||||
else ifeq ($(findstring icc,$(COMPILER)),icc)
|
||||
LINKER_FLAGS += -static-intel -no-intel-extensions
|
||||
|
||||
ifneq "$(DEBUG)" "true"
|
||||
COMPILER_FLAGS += -funroll-all-loops -ipo -wd11076 -wd11074
|
||||
LINKER_FLAGS += -cxxlib-nostd -Wl,--no-undefined,-z,notext,--gc-sections -ipo
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJECTS_BIN := $(OBJECTS:%.cpp=$(BINARY_DIR)/%.o)
|
||||
|
||||
$(BINARY_DIR)/%.o: %.cpp
|
||||
$(COMPILER) $(INCLUDE) $(COMPILER_FLAGS) -o $(subst $(SOURCES)/,,$@) -c $<
|
||||
|
||||
compile:
|
||||
mkdir -p $(BINARY_DIR)
|
||||
$(MAKE) $(PROJECT)
|
||||
|
||||
$(PROJECT): $(OBJECTS_BIN)
|
||||
$(COMPILER) $(INCLUDE) $(subst $(SOURCES)/,,$(OBJECTS_BIN)) $(LINKER_FLAGS) -o $(BINARY_DIR)/$(BINARY_OUTPUT)
|
||||
|
||||
release:
|
||||
$(MAKE) compile DEBUG=false
|
||||
|
||||
debug:
|
||||
$(MAKE) compile DEBUG=true
|
||||
|
||||
all:
|
||||
$(MAKE) compile DEBUG=true
|
||||
$(MAKE) compile DEBUG=false
|
||||
|
||||
clean:
|
||||
rm -rf release/*.o
|
||||
rm -rf release/$(BINARY_OUTPUT)
|
||||
rm -rf debug/*.o
|
||||
rm -rf debug/$(BINARY_OUTPUT)
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
//
|
||||
|
||||
#include <winver.h>
|
||||
#include <../include/resource.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION PRODUCT_VERSION_DWORD
|
||||
PRODUCTVERSION PRODUCT_VERSION_DWORD
|
||||
FILEOS 0x40004
|
||||
FILETYPE 0x2
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904E4"
|
||||
{
|
||||
VALUE "CompanyName", PRODUCT_AUTHOR "\0"
|
||||
VALUE "FileDescription", PRODUCT_DESCRIPTION "\0"
|
||||
VALUE "FileVersion", PRODUCT_VERSION "\0"
|
||||
VALUE "OriginalFilename", PRODUCT_ORIGINAL_NAME "\0"
|
||||
VALUE "LegalCopyright", PRODUCT_COPYRIGHT "\0"
|
||||
VALUE "LegalTrademarks", PRODUCT_LEGAL "\0"
|
||||
VALUE "ProductName", PRODUCT_NAME "\0"
|
||||
VALUE "ProductVersion", PRODUCT_VERSION "\0"
|
||||
VALUE "InternalName", PRODUCT_INTERNAL_NAME "\0"
|
||||
}
|
||||
}
|
||||
#ifndef NOLANGINFO
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x400, 1252
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="source">
|
||||
<UniqueIdentifier>{8d3352c3-bb0c-4e87-bb5d-044bb9ec5e13}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="include">
|
||||
<UniqueIdentifier>{e529241e-773e-4084-a737-060aa8396cba}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="project">
|
||||
<UniqueIdentifier>{fe17a93f-cd53-4c35-b79b-969c4967865e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="include\engine">
|
||||
<UniqueIdentifier>{f98ff5ec-055a-46cd-b5b1-462ef4c1c73e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="include\crlib">
|
||||
<UniqueIdentifier>{76a583d1-8f55-451b-8516-2f7cce4d1875}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\resource.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\const.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\eiface.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\extdll.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\meta_api.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\progdefs.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\util.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\yapb.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\engine\model.h">
|
||||
<Filter>include\engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-alloc.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-array.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-basic.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-binheap.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-complete.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-dict.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-files.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-http.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-lambda.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-library.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-logger.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-math.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-movable.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-platform.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-random.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-string.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-twin.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-ulz.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-uniqueptr.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-vector.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-color.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\crlib\cr-hook.h">
|
||||
<Filter>include\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\config.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\graph.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\manager.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\utils.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\control.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\message.h">
|
||||
<Filter>include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\source\chatlib.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\navigate.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\support.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\manager.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\combat.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\engine.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\control.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\basecode.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\graph.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\android.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\message.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\linkage.cpp">
|
||||
<Filter>source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="yapb.rc">
|
||||
<Filter>project</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile">
|
||||
<Filter>project</Filter>
|
||||
</None>
|
||||
<None Include="..\source\Android.mk">
|
||||
<Filter>project</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
include $(XASH3D_CONFIG)
|
||||
|
||||
LOCAL_MODULE := yapb
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a-hard)
|
||||
LOCAL_MODULE_FILENAME = libyapb_hardfp
|
||||
endif
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include \
|
||||
$(LOCAL_PATH)/../include/engine
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
basecode.cpp \
|
||||
manager.cpp \
|
||||
message.cpp \
|
||||
chatlib.cpp \
|
||||
combat.cpp \
|
||||
control.cpp \
|
||||
engine.cpp \
|
||||
linkage.cpp \
|
||||
navigate.cpp \
|
||||
support.cpp \
|
||||
graph.cpp \
|
||||
|
||||
LOCAL_CFLAGS += -O3 -std=c++11 -DLINUX -D_LINUX -DPOSIX -pipe -fno-strict-aliasing -Wall -Werror -Wno-array-bounds
|
||||
LOCAL_CPPFLAGS += -fno-exceptions -fno-rtti
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
|
@ -16,7 +23,7 @@ CR_EXPORT int Server_GetBlendingInterface (int version, struct sv_blending_inter
|
|||
// of the body move, which bones, which hitboxes and how) between the server and the game DLL.
|
||||
// some MODs can be using a different hitbox scheme than the standard one.
|
||||
|
||||
auto api_GetBlendingInterface = game.lib ().resolve <int (*) (int, struct sv_blending_interface_s **, struct engine_studio_api_s *, float *, float *)> (__FUNCTION__);
|
||||
auto api_GetBlendingInterface = game.lib ().resolve <decltype (&Server_GetBlendingInterface)> (__FUNCTION__);
|
||||
|
||||
if (!api_GetBlendingInterface) {
|
||||
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,16 +1,23 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_chat ("yb_chat", "1", "Enables or disables bots chat functionality.");
|
||||
ConVar cv_chat ("ub_chat", "1", "Enables or disables bots chat functionality.");
|
||||
|
||||
void BotUtils::stripTags (String &line) {
|
||||
void BotSupport::stripTags (String &line) {
|
||||
if (line.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -30,7 +37,7 @@ void BotUtils::stripTags (String &line) {
|
|||
}
|
||||
}
|
||||
|
||||
void BotUtils::humanizePlayerName (String &playerName) {
|
||||
void BotSupport::humanizePlayerName (String &playerName) {
|
||||
if (playerName.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -44,14 +51,14 @@ void BotUtils::humanizePlayerName (String &playerName) {
|
|||
}
|
||||
|
||||
// sometimes switch name to lower characters, only valid for the english languge
|
||||
if (rg.chance (8) && strcmp (yb_language.str (), "en") == 0) {
|
||||
if (rg.chance (8) && strcmp (cv_language.str (), "en") == 0) {
|
||||
playerName.lowercase ();
|
||||
}
|
||||
}
|
||||
|
||||
void BotUtils::addChatErrors (String &line) {
|
||||
void BotSupport::addChatErrors (String &line) {
|
||||
// sometimes switch name to lower characters, only valid for the english languge
|
||||
if (rg.chance (8) && strcmp (yb_language.str (), "en") == 0) {
|
||||
if (rg.chance (8) && strcmp (cv_language.str (), "en") == 0) {
|
||||
line.lowercase ();
|
||||
}
|
||||
auto length = line.length ();
|
||||
|
|
@ -72,10 +79,10 @@ void BotUtils::addChatErrors (String &line) {
|
|||
}
|
||||
}
|
||||
|
||||
bool BotUtils::checkKeywords (const String &line, String &reply) {
|
||||
bool BotSupport::checkKeywords (StringRef line, String &reply) {
|
||||
// this function checks is string contain keyword, and generates reply to it
|
||||
|
||||
if (!yb_chat.bool_ () || line.empty ()) {
|
||||
if (!cv_chat.bool_ () || line.empty ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +91,7 @@ bool BotUtils::checkKeywords (const String &line, String &reply) {
|
|||
|
||||
// check is keyword has occurred in message
|
||||
if (line.find (keyword) != String::InvalidIndex) {
|
||||
StringArray &usedReplies = factory.usedReplies;
|
||||
auto &usedReplies = factory.usedReplies;
|
||||
|
||||
if (usedReplies.length () >= factory.replies.length () / 4) {
|
||||
usedReplies.clear ();
|
||||
|
|
@ -92,7 +99,7 @@ bool BotUtils::checkKeywords (const String &line, String &reply) {
|
|||
|
||||
if (!factory.replies.empty ()) {
|
||||
bool replyUsed = false;
|
||||
const String &choosenReply = factory.replies.random ();
|
||||
StringRef choosenReply = factory.replies.random ();
|
||||
|
||||
// don't say this twice
|
||||
for (auto &used : usedReplies) {
|
||||
|
|
@ -120,13 +127,13 @@ bool BotUtils::checkKeywords (const String &line, String &reply) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Bot::prepareChatMessage (const String &message) {
|
||||
void Bot::prepareChatMessage (StringRef message) {
|
||||
// this function parses messages from the botchat, replaces keywords and converts names into a more human style
|
||||
|
||||
if (!yb_chat.bool_ () || message.empty ()) {
|
||||
if (!cv_chat.bool_ () || message.empty ()) {
|
||||
return;
|
||||
}
|
||||
m_chatBuffer.assign (message.chars ());
|
||||
m_chatBuffer = message;
|
||||
|
||||
// must be called before return or on the end
|
||||
auto finishPreparation = [&] () {
|
||||
|
|
@ -145,7 +152,7 @@ void Bot::prepareChatMessage (const String &message) {
|
|||
}
|
||||
|
||||
// get the humanized name out of client
|
||||
auto humanizedName = [] (int index) -> String {
|
||||
auto humanizedName = [] (int index) -> StringRef {
|
||||
auto ent = game.playerOfIndex (index);
|
||||
|
||||
if (!util.isPlayer (ent)) {
|
||||
|
|
@ -158,7 +165,7 @@ void Bot::prepareChatMessage (const String &message) {
|
|||
};
|
||||
|
||||
// find highfrag player
|
||||
auto getHighfragPlayer = [&] () -> String {
|
||||
auto getHighfragPlayer = [&] () -> StringRef {
|
||||
int highestFrags = -1;
|
||||
int index = 0;
|
||||
|
||||
|
|
@ -179,7 +186,7 @@ void Bot::prepareChatMessage (const String &message) {
|
|||
};
|
||||
|
||||
// get roundtime
|
||||
auto getRoundTime = [] () -> String {
|
||||
auto getRoundTime = [] () -> StringRef {
|
||||
auto roundTimeSecs = static_cast <int> (bots.getRoundEndTime () - game.time ());
|
||||
|
||||
String roundTime;
|
||||
|
|
@ -189,12 +196,12 @@ void Bot::prepareChatMessage (const String &message) {
|
|||
};
|
||||
|
||||
// get bot's victim
|
||||
auto getMyVictim = [&] () -> String {;
|
||||
auto getMyVictim = [&] () -> StringRef {;
|
||||
return humanizedName (game.indexOfPlayer (m_lastVictim));
|
||||
};
|
||||
|
||||
// get the game name alias
|
||||
auto getGameName = [] () -> String {
|
||||
auto getGameName = [] () -> StringRef {
|
||||
String gameName;
|
||||
|
||||
if (game.is (GameFlags::ConditionZero)) {
|
||||
|
|
@ -217,7 +224,7 @@ void Bot::prepareChatMessage (const String &message) {
|
|||
};
|
||||
|
||||
// get enemy or teammate alive
|
||||
auto getPlayerAlive = [&] (bool needsEnemy) -> String {
|
||||
auto getPlayerAlive = [&] (bool needsEnemy) -> StringRef {
|
||||
for (const auto &client : util.getClients ()) {
|
||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.ent == ent ()) {
|
||||
continue;
|
||||
|
|
@ -317,19 +324,19 @@ bool Bot::isReplyingToChat () {
|
|||
void Bot::checkForChat () {
|
||||
|
||||
// say a text every now and then
|
||||
if (rg.chance (30) || m_notKilled || !yb_chat.bool_ ()) {
|
||||
if (rg.chance (30) || m_notKilled || !cv_chat.bool_ ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// bot chatting turned on?
|
||||
if (m_lastChatTime + rg.float_ (6.0f, 10.0f) < game.time () && bots.getLastChatTimestamp () + rg.float_ (2.5f, 5.0f) < game.time () && !isReplyingToChat ()) {
|
||||
if (conf.hasChatBank (Chat::Dead)) {
|
||||
const auto &phrase = conf.pickRandomFromChatBank (Chat::Dead);
|
||||
StringRef phrase = conf.pickRandomFromChatBank (Chat::Dead);
|
||||
bool sayBufferExists = false;
|
||||
|
||||
// search for last messages, sayed
|
||||
for (auto &sentence : m_sayTextBuffer.lastUsedSentences) {
|
||||
if (strncmp (sentence.chars (), phrase.chars (), sentence.length ()) == 0) {
|
||||
if (phrase.startsWith (sentence)) {
|
||||
sayBufferExists = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -354,20 +361,11 @@ void Bot::checkForChat () {
|
|||
}
|
||||
}
|
||||
|
||||
void Bot::say (const char *text) {
|
||||
void Bot::sendToChat (StringRef message, bool teamOnly) {
|
||||
// this function prints saytext message to all players
|
||||
|
||||
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
||||
if (message.empty () || !cv_chat.bool_ ()) {
|
||||
return;
|
||||
}
|
||||
issueCommand ("say \"%s\"", text);
|
||||
}
|
||||
|
||||
void Bot::sayTeam (const char *text) {
|
||||
// this function prints saytext message only for teammates
|
||||
|
||||
if (strings.isEmpty (text) || !yb_chat.bool_ ()) {
|
||||
return;
|
||||
}
|
||||
issueCommand ("say_team \"%s\"", text);
|
||||
issueCommand ("%s \"%s\"", teamOnly ? "say_team" : "say", message);
|
||||
}
|
||||
|
|
@ -1,18 +1,26 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_shoots_thru_walls ("yb_shoots_thru_walls", "2", "Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.", true, 0.0f, 3.0f);
|
||||
ConVar yb_ignore_enemies ("yb_ignore_enemies", "0", "Enables or disables searching world for enemies.");
|
||||
ConVar yb_check_enemy_rendering ("yb_check_enemy_rendering", "0", "Enables or disables checking enemy rendering flags. Useful for some mods.");
|
||||
ConVar yb_stab_close_enemies ("yb_stab_close_enemies", "1", "Enables or disables bot ability to stab the enemy with knife if bot is in good condition.");
|
||||
ConVar mp_friendlyfire ("mp_friendlyfire", nullptr, Var::NoRegister);
|
||||
ConVar cv_shoots_thru_walls ("ub_shoots_thru_walls", "2", "Specifies whether bots able to fire at enemies behind the wall, if they hearing or suspecting them.", true, 0.0f, 3.0f);
|
||||
ConVar cv_ignore_enemies ("ub_ignore_enemies", "0", "Enables or disables searching world for enemies.");
|
||||
ConVar cv_check_enemy_rendering ("ub_check_enemy_rendering", "0", "Enables or disables checking enemy rendering flags. Useful for some mods.");
|
||||
ConVar cv_stab_close_enemies ("ub_stab_close_enemies", "1", "Enables or disables bot ability to stab the enemy with knife if bot is in good condition.");
|
||||
|
||||
ConVar mp_friendlyfire ("mp_friendlyfire", nullptr, Var::GameRef);
|
||||
|
||||
int Bot::numFriendsNear (const Vector &origin, float radius) {
|
||||
int count = 0;
|
||||
|
|
@ -45,7 +53,7 @@ int Bot::numEnemiesNear (const Vector &origin, float radius) {
|
|||
}
|
||||
|
||||
bool Bot::isEnemyHidden (edict_t *enemy) {
|
||||
if (!yb_check_enemy_rendering.bool_ () || game.isNullEntity (enemy)) {
|
||||
if (!cv_check_enemy_rendering.bool_ () || game.isNullEntity (enemy)) {
|
||||
return false;
|
||||
}
|
||||
entvars_t &v = enemy->v;
|
||||
|
|
@ -123,8 +131,8 @@ bool Bot::checkBodyParts (edict_t *target) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const float standFeet = 34.0f;
|
||||
const float crouchFeet = 14.0f;
|
||||
constexpr auto standFeet = 34.0f;
|
||||
constexpr auto crouchFeet = 14.0f;
|
||||
|
||||
if (target->v.flags & FL_DUCKING) {
|
||||
spot.z = target->v.origin.z - crouchFeet;
|
||||
|
|
@ -132,7 +140,7 @@ bool Bot::checkBodyParts (edict_t *target) {
|
|||
else {
|
||||
spot.z = target->v.origin.z - standFeet;
|
||||
}
|
||||
game.testLine (eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
|
||||
if (result.flFraction >= 1.0f) {
|
||||
m_enemyParts |= Visibility::Other;
|
||||
|
|
@ -147,7 +155,7 @@ bool Bot::checkBodyParts (edict_t *target) {
|
|||
Vector perp (-dir.y, dir.x, 0.0f);
|
||||
spot = target->v.origin + Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
||||
|
||||
game.testLine (eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
|
||||
if (result.flFraction >= 1.0f) {
|
||||
m_enemyParts |= Visibility::Other;
|
||||
|
|
@ -157,7 +165,7 @@ bool Bot::checkBodyParts (edict_t *target) {
|
|||
}
|
||||
spot = target->v.origin - Vector (perp.x * edgeOffset, perp.y * edgeOffset, 0);
|
||||
|
||||
game.testLine (eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
game.testLineChannel (TraceChannel::Enemy, eyes, spot, TraceIgnore::Everything, self, &result);
|
||||
|
||||
if (result.flFraction >= 1.0f) {
|
||||
m_enemyParts |= Visibility::Other;
|
||||
|
|
@ -173,11 +181,11 @@ bool Bot::seesEnemy (edict_t *player, bool ignoreFOV) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (util.isPlayer (pev->dmg_inflictor) && game.getTeam (pev->dmg_inflictor) != m_team) {
|
||||
if (cv_whose_your_daddy.bool_ () && util.isPlayer (pev->dmg_inflictor) && game.getTeam (pev->dmg_inflictor) != m_team) {
|
||||
ignoreFOV = true;
|
||||
}
|
||||
|
||||
if ((ignoreFOV || isInViewCone (player->v.origin)) && checkBodyParts (player)) {
|
||||
if ((ignoreFOV || isInViewCone (player->v.origin)) && isEnemyInFrustum (player) && checkBodyParts (player)) {
|
||||
m_seeEnemyTime = game.time ();
|
||||
m_lastEnemy = player;
|
||||
m_lastEnemyOrigin = m_enemyOrigin;
|
||||
|
|
@ -201,14 +209,12 @@ bool Bot::lookupEnemies () {
|
|||
// this function tries to find the best suitable enemy for the bot
|
||||
|
||||
// do not search for enemies while we're blinded, or shooting disabled by user
|
||||
if (m_enemyIgnoreTimer > game.time () || m_blindTime > game.time () || yb_ignore_enemies.bool_ ()) {
|
||||
if (m_enemyIgnoreTimer > game.time () || m_blindTime > game.time () || cv_ignore_enemies.bool_ ()) {
|
||||
return false;
|
||||
}
|
||||
edict_t *player, *newEnemy = nullptr;
|
||||
float nearestDistance = cr::square (m_viewDistance);
|
||||
|
||||
extern ConVar yb_whose_your_daddy;
|
||||
|
||||
// clear suspected flag
|
||||
if (!game.isNullEntity (m_enemy) && (m_states & Sense::SeeingEnemy)) {
|
||||
m_states &= ~Sense::SuspectEnemy;
|
||||
|
|
@ -244,12 +250,12 @@ bool Bot::lookupEnemies () {
|
|||
player = client.ent;
|
||||
|
||||
// check the engine PVS
|
||||
if (!game.checkVisibility (player, set)) {
|
||||
if (!isEnemyInFrustum (player) || !game.checkVisibility (player, set)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// extra skill player can see thru smoke... if beeing attacked
|
||||
if ((player->v.button & (IN_ATTACK | IN_ATTACK2)) && m_viewDistance < m_maxViewDistance && yb_whose_your_daddy.bool_ ()) {
|
||||
if ((player->v.button & (IN_ATTACK | IN_ATTACK2)) && m_viewDistance < m_maxViewDistance && cv_whose_your_daddy.bool_ ()) {
|
||||
nearestDistance = cr::square (m_maxViewDistance);
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +308,7 @@ bool Bot::lookupEnemies () {
|
|||
}
|
||||
m_targetEntity = nullptr; // stop following when we see an enemy...
|
||||
|
||||
if (yb_whose_your_daddy.bool_ ()) {
|
||||
if (cv_whose_your_daddy.bool_ ()) {
|
||||
m_enemySurpriseTime = m_actualReactionTime * 0.5f;
|
||||
}
|
||||
else {
|
||||
|
|
@ -373,7 +379,7 @@ bool Bot::lookupEnemies () {
|
|||
}
|
||||
|
||||
// if no enemy visible check if last one shoot able through wall
|
||||
if (yb_shoots_thru_walls.bool_ () && m_difficulty >= 2 && isPenetrableObstacle (newEnemy->v.origin)) {
|
||||
if (cv_shoots_thru_walls.bool_ () && rg.chance (conf.getDifficultyTweaks (m_difficulty)->seenThruPct) && m_difficulty >= Difficulty::Normal && isPenetrableObstacle (newEnemy->v.origin)) {
|
||||
m_seeEnemyTime = game.time ();
|
||||
|
||||
m_states |= Sense::SuspectEnemy;
|
||||
|
|
@ -412,7 +418,7 @@ Vector Bot::getBodyOffsetError (float distance) {
|
|||
}
|
||||
|
||||
if (m_aimErrorTime < game.time ()) {
|
||||
const float error = distance / (cr::clamp (m_difficulty, 1, 4) * 1000.0f);
|
||||
const float error = distance / (cr::clamp (m_difficulty, 1, 3) * 1000.0f);
|
||||
Vector &maxs = m_enemy->v.maxs, &mins = m_enemy->v.mins;
|
||||
|
||||
m_aimLastError = Vector (rg.float_ (mins.x * error, maxs.x * error), rg.float_ (mins.y * error, maxs.y * error), rg.float_ (mins.z * error, maxs.z * error));
|
||||
|
|
@ -436,7 +442,7 @@ const Vector &Bot::getEnemyBodyOffset () {
|
|||
float distance = (m_enemy->v.origin - pev->origin).length ();
|
||||
|
||||
// do not aim at head, at long distance (only if not using sniper weapon)
|
||||
if ((m_enemyParts & Visibility::Body) && !usesSniper () && distance > (m_difficulty > 2 ? 2000.0f : 1000.0f)) {
|
||||
if ((m_enemyParts & Visibility::Body) && !usesSniper () && distance > (m_difficulty > Difficulty::Normal ? 2000.0f : 1000.0f)) {
|
||||
m_enemyParts &= ~Visibility::Head;
|
||||
}
|
||||
|
||||
|
|
@ -446,7 +452,7 @@ const Vector &Bot::getEnemyBodyOffset () {
|
|||
}
|
||||
Vector aimPos = m_enemy->v.origin;
|
||||
|
||||
if (m_difficulty > 2) {
|
||||
if (m_difficulty > Difficulty::Normal) {
|
||||
aimPos += (m_enemy->v.velocity - pev->velocity) * (getFrameInterval () * 1.25f);
|
||||
}
|
||||
|
||||
|
|
@ -455,14 +461,15 @@ const Vector &Bot::getEnemyBodyOffset () {
|
|||
aimPos += getBodyOffsetError (distance);
|
||||
}
|
||||
else {
|
||||
bool useBody = !usesPistol () && distance >= kSprayDistance && distance < 3072.0f;
|
||||
|
||||
|
||||
// now take in account different parts of enemy body
|
||||
if (m_enemyParts & (Visibility::Head | Visibility::Body)) {
|
||||
int headshotFreq[5] = { 20, 40, 60, 80, 100 };
|
||||
// forced to use body?
|
||||
bool useBody = !usesPistol () && distance >= kSprayDistance && distance < 3072.0f;
|
||||
|
||||
// now check is our skill match to aim at head, else aim at enemy body
|
||||
if (rg.chance (headshotFreq[m_difficulty]) && !useBody) {
|
||||
if (rg.chance (conf.getDifficultyTweaks (m_difficulty)->headshotPct) && !useBody) {
|
||||
aimPos.z = headOffset (m_enemy) + getEnemyBodyOffsetCorrection (distance);
|
||||
}
|
||||
else {
|
||||
|
|
@ -488,7 +495,7 @@ const Vector &Bot::getEnemyBodyOffset () {
|
|||
m_lastEnemyOrigin = aimPos;
|
||||
|
||||
// add some error to unskilled bots
|
||||
if (m_difficulty < 3) {
|
||||
if (m_difficulty < Difficulty::Hard) {
|
||||
m_enemyOrigin += getBodyOffsetError (distance);
|
||||
}
|
||||
return m_enemyOrigin;
|
||||
|
|
@ -572,11 +579,11 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
|
|||
// this function returns true if enemy can be shoot through some obstacle, false otherwise.
|
||||
// credits goes to Immortal_BLG
|
||||
|
||||
if (yb_shoots_thru_walls.int_ () == 2) {
|
||||
if (cv_shoots_thru_walls.int_ () == 2) {
|
||||
return isPenetrableObstacle2 (dest);
|
||||
}
|
||||
|
||||
if (m_isUsingGrenade || m_difficulty < 2) {
|
||||
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal) {
|
||||
return false;
|
||||
}
|
||||
int penetratePower = conf.findWeaponById (m_currentWeapon).penetratePower;
|
||||
|
|
@ -593,7 +600,7 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
|
|||
const Vector &source = tr.vecEndPos;
|
||||
game.testLine (dest, source, TraceIgnore::Monsters, ent (), &tr);
|
||||
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
if ((tr.vecEndPos - dest).lengthSq () > cr::square (800.0f)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -623,7 +630,7 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
|
|||
bool Bot::isPenetrableObstacle2 (const Vector &dest) {
|
||||
// this function returns if enemy can be shoot through some obstacle
|
||||
|
||||
if (m_isUsingGrenade || m_difficulty < 2 || !conf.findWeaponById (m_currentWeapon).penetratePower) {
|
||||
if (m_isUsingGrenade || m_difficulty < Difficulty::Normal || !conf.findWeaponById (m_currentWeapon).penetratePower) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -638,7 +645,7 @@ bool Bot::isPenetrableObstacle2 (const Vector &dest) {
|
|||
|
||||
game.testLine (source, dest, TraceIgnore::Everything, ent (), &tr);
|
||||
|
||||
while (tr.flFraction != 1.0f && numHits < 3) {
|
||||
while (!cr::fequal (tr.flFraction, 1.0f) && numHits < 3) {
|
||||
numHits++;
|
||||
thikness++;
|
||||
|
||||
|
|
@ -686,8 +693,8 @@ bool Bot::needToPauseFiring (float distance) {
|
|||
else if (distance < kDoubleSprayDistance) {
|
||||
offset = 10.0f;
|
||||
}
|
||||
const float xPunch = cr::degreesToRadians (pev->punchangle.x);
|
||||
const float yPunch = cr::degreesToRadians (pev->punchangle.y);
|
||||
const float xPunch = cr::deg2rad (pev->punchangle.x);
|
||||
const float yPunch = cr::deg2rad (pev->punchangle.y);
|
||||
|
||||
const float interval = getFrameInterval ();
|
||||
const float tolerance = (100.0f - m_difficulty * 25.0f) / 99.0f;
|
||||
|
|
@ -772,7 +779,7 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
|
|||
}
|
||||
|
||||
// else is the bot holding a zoomable rifle?
|
||||
else if (m_difficulty < 3 && usesZoomableRifle () && m_zoomCheckTime < game.time ()) {
|
||||
else if (m_difficulty < Difficulty::Hard && usesZoomableRifle () && m_zoomCheckTime < game.time ()) {
|
||||
// should the bot switch to zoomed mode?
|
||||
if (distance > 800.0f && pev->fov >= 90.0f) {
|
||||
pev->button |= IN_ATTACK2;
|
||||
|
|
@ -786,13 +793,13 @@ void Bot::selectWeapons (float distance, int index, int id, int choosen) {
|
|||
}
|
||||
|
||||
// we're should stand still before firing sniper weapons, else sniping is useless..
|
||||
if (usesSniper () && (m_states & (Sense::SeeingEnemy | Sense::SuspectEnemy)) && !m_isReloading && pev->velocity.lengthSq () > 0.0f) {
|
||||
if (usesSniper () && (m_aimFlags & (AimFlags::Enemy | AimFlags::LastEnemy)) && !m_isReloading && pev->velocity.lengthSq () > 0.0f) {
|
||||
m_moveSpeed = 0.0f;
|
||||
m_strafeSpeed = 0.0f;
|
||||
m_navTimeset = game.time ();
|
||||
|
||||
if (cr::abs (pev->velocity.x) > 5.0f || cr::abs (pev->velocity.y) > 5.0f || cr::abs (pev->velocity.z) > 5.0f) {
|
||||
m_sniperStopTime = game.time () + 2.5f;
|
||||
m_sniperStopTime = game.time () + 2.0f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -880,13 +887,13 @@ void Bot::fireWeapons () {
|
|||
int weapons = pev->weapons;
|
||||
|
||||
// if jason mode use knife only
|
||||
if (yb_jasonmode.bool_ ()) {
|
||||
if (cv_jasonmode.bool_ ()) {
|
||||
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
|
||||
return;
|
||||
}
|
||||
|
||||
// use knife if near and good difficulty (l33t dude!)
|
||||
if (yb_stab_close_enemies.bool_ () && m_difficulty >= 3 && pev->health > 80.0f && !game.isNullEntity (enemy) && pev->health >= enemy->v.health && distance < 100.0f && !isOnLadder () && !isGroupOfEnemies (pev->origin)) {
|
||||
if (cv_stab_close_enemies.bool_ () && m_difficulty >= Difficulty::Hard && pev->health > 80.0f && !game.isNullEntity (enemy) && pev->health >= enemy->v.health && distance < 100.0f && !isOnLadder () && !isGroupOfEnemies (pev->origin)) {
|
||||
selectWeapons (distance, selectIndex, selectId, choosenWeapon);
|
||||
return;
|
||||
}
|
||||
|
|
@ -945,7 +952,7 @@ bool Bot::isWeaponBadAtDistance (int weaponIndex, float distance) {
|
|||
|
||||
auto &info = conf.getWeapons ();
|
||||
|
||||
if (m_difficulty < 2 || !hasSecondaryWeapon ()) {
|
||||
if (m_difficulty < Difficulty::Normal || !hasSecondaryWeapon ()) {
|
||||
return false;
|
||||
}
|
||||
int wid = info[weaponIndex].id;
|
||||
|
|
@ -1138,7 +1145,7 @@ void Bot::attackMovement () {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_difficulty >= 3 && (m_jumpTime + 5.0f < game.time () && isOnFloor () && rg.int_ (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.length2d () > 120.0f) && !usesSniper ()) {
|
||||
if (m_difficulty >= Difficulty::Hard && (m_jumpTime + 5.0f < game.time () && isOnFloor () && rg.int_ (0, 1000) < (m_isReloading ? 8 : 2) && pev->velocity.length2d () > 120.0f) && !usesSniper ()) {
|
||||
pev->button |= IN_JUMP;
|
||||
}
|
||||
|
||||
|
|
@ -1383,7 +1390,7 @@ void Bot::selectBestWeapon () {
|
|||
// this function chooses best weapon, from weapons that bot currently own, and change
|
||||
// current weapon to best one.
|
||||
|
||||
if (yb_jasonmode.bool_ ()) {
|
||||
if (cv_jasonmode.bool_ ()) {
|
||||
// if knife mode activated, force bot to use knife
|
||||
selectWeaponByName ("weapon_knife");
|
||||
return;
|
||||
|
|
@ -1502,7 +1509,7 @@ void Bot::decideFollowUser () {
|
|||
|
||||
void Bot::updateTeamCommands () {
|
||||
// prevent spamming
|
||||
if (m_timeTeamOrder > game.time () + 2.0f || game.is (GameFlags::FreeForAll) || !yb_radio_mode.int_ ()) {
|
||||
if (m_timeTeamOrder > game.time () + 2.0f || game.is (GameFlags::FreeForAll) || !cv_radio_mode.int_ ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1524,17 +1531,17 @@ void Bot::updateTeamCommands () {
|
|||
|
||||
// has teammates?
|
||||
if (memberNear) {
|
||||
if (m_personality == Personality::Rusher && yb_radio_mode.int_ () == 2) {
|
||||
if (m_personality == Personality::Rusher && cv_radio_mode.int_ () == 2) {
|
||||
pushRadioMessage (Radio::StormTheFront);
|
||||
}
|
||||
else if (m_personality != Personality::Rusher && yb_radio_mode.int_ () == 2) {
|
||||
else if (m_personality != Personality::Rusher && cv_radio_mode.int_ () == 2) {
|
||||
pushRadioMessage (Radio::TeamFallback);
|
||||
}
|
||||
}
|
||||
else if (memberExists && yb_radio_mode.int_ () == 1) {
|
||||
else if (memberExists && cv_radio_mode.int_ () == 1) {
|
||||
pushRadioMessage (Radio::TakingFireNeedAssistance);
|
||||
}
|
||||
else if (memberExists && yb_radio_mode.int_ () == 2) {
|
||||
else if (memberExists && cv_radio_mode.int_ () == 2) {
|
||||
pushChatterMessage (Chatter::ScaredEmotion);
|
||||
}
|
||||
m_timeTeamOrder = game.time () + rg.float_ (15.0f, 30.0f);
|
||||
|
|
@ -1,58 +1,62 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_display_menu_text ("yb_display_menu_text", "1", "Enables or disables display menu text, when players asks for menu. Useful only for Android.");
|
||||
ConVar yb_password ("yb_password", "", "The value (password) for the setinfo key, if user set's correct password, he's gains access to bot commands and menus.", false, 0.0f, 0.0f, Var::Password);
|
||||
ConVar yb_password_key ("yb_password_key", "_ybpw", "The name of setinfo key used to store password to bot commands and menus", false);
|
||||
ConVar cv_display_menu_text ("ub_display_menu_text", "1", "Enables or disables display menu text, when players asks for menu. Useful only for Android.");
|
||||
ConVar cv_password ("ub_password", "", "The value (password) for the setinfo key, if user set's correct password, he's gains access to bot commands and menus.", false, 0.0f, 0.0f, Var::Password);
|
||||
ConVar cv_password_key ("ub_password_key", "_ubpw", "The name of setinfo key used to store password to bot commands and menus.", false);
|
||||
|
||||
int BotControl::cmdAddBot () {
|
||||
enum args { alias = 1, difficulty, personality, team, model, name, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
|
||||
// this is duplicate error as in main bot creation code, but not to be silent
|
||||
if (!graph.length () || graph.hasChanged ()) {
|
||||
ctrl.msg ("There is no graph found or graph is changed. Cannot create bot.");
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
||||
// give a chance to use additional args
|
||||
m_args.resize (max);
|
||||
|
||||
// if team is specified, modify args to set team
|
||||
if (m_args[alias].find ("_ct", 0) != String::InvalidIndex) {
|
||||
if (strValue (alias).find ("_ct", 0) != String::InvalidIndex) {
|
||||
m_args.set (team, "2");
|
||||
}
|
||||
else if (m_args[alias].find ("_t", 0) != String::InvalidIndex) {
|
||||
else if (strValue (alias).find ("_t", 0) != String::InvalidIndex) {
|
||||
m_args.set (team, "1");
|
||||
}
|
||||
|
||||
// if highskilled bot is requsted set personality to rusher and maxout difficulty
|
||||
if (m_args[alias].find ("hs", 0) != String::InvalidIndex) {
|
||||
if (strValue (alias).find ("hs", 0) != String::InvalidIndex) {
|
||||
m_args.set (difficulty, "4");
|
||||
m_args.set (personality, "1");
|
||||
}
|
||||
bots.addbot (m_args[name], m_args[difficulty], m_args[personality], m_args[team], m_args[model], true);
|
||||
bots.addbot (strValue (name), strValue (difficulty), strValue (personality), strValue (team), strValue (model), true);
|
||||
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
||||
int BotControl::cmdKickBot () {
|
||||
enum args { alias = 1, team, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, team };
|
||||
|
||||
// if team is specified, kick from specified tram
|
||||
if (m_args[alias].find ("_ct", 0) != String::InvalidIndex || getInt (team) == 2 || getStr (team) == "ct") {
|
||||
if (strValue (alias).find ("_ct", 0) != String::InvalidIndex || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
bots.kickFromTeam (Team::CT);
|
||||
}
|
||||
else if (m_args[alias].find ("_t", 0) != String::InvalidIndex || getInt (team) == 1 || getStr (team) == "t") {
|
||||
else if (strValue (alias).find ("_t", 0) != String::InvalidIndex || intValue (team) == 1 || strValue (team) == "t") {
|
||||
bots.kickFromTeam (Team::Terrorist);
|
||||
}
|
||||
else {
|
||||
|
|
@ -62,13 +66,10 @@ int BotControl::cmdKickBot () {
|
|||
}
|
||||
|
||||
int BotControl::cmdKickBots () {
|
||||
enum args { alias = 1, instant, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, instant };
|
||||
|
||||
// check if we're need to remove bots instantly
|
||||
auto kickInstant = getStr (instant) == "instant";
|
||||
auto kickInstant = strValue (instant) == "instant";
|
||||
|
||||
// kick the bots
|
||||
bots.kickEveryone (kickInstant);
|
||||
|
|
@ -79,14 +80,11 @@ int BotControl::cmdKickBots () {
|
|||
int BotControl::cmdKillBots () {
|
||||
enum args { alias = 1, team, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
|
||||
// if team is specified, kick from specified tram
|
||||
if (m_args[alias].find ("_ct", 0) != String::InvalidIndex || getInt (team) == 2 || getStr (team) == "ct") {
|
||||
if (strValue (alias).find ("_ct", 0) != String::InvalidIndex || intValue (team) == 2 || strValue (team) == "ct") {
|
||||
bots.killAllBots (Team::CT);
|
||||
}
|
||||
else if (m_args[alias].find ("_t", 0) != String::InvalidIndex || getInt (team) == 1 || getStr (team) == "t") {
|
||||
else if (strValue (alias).find ("_t", 0) != String::InvalidIndex || intValue (team) == 1 || strValue (team) == "t") {
|
||||
bots.killAllBots (Team::Terrorist);
|
||||
}
|
||||
else {
|
||||
|
|
@ -96,29 +94,23 @@ int BotControl::cmdKillBots () {
|
|||
}
|
||||
|
||||
int BotControl::cmdFill () {
|
||||
enum args { alias = 1, team, count, difficulty, personality, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, team, count, difficulty, personality };
|
||||
|
||||
if (!hasArg (team)) {
|
||||
return BotCommandResult::BadFormat;
|
||||
}
|
||||
bots.serverFill (getInt (team), hasArg (personality) ? getInt (personality) : -1, hasArg (difficulty) ? getInt (difficulty) : -1, hasArg (count) ? getInt (count) : -1);
|
||||
bots.serverFill (intValue (team), hasArg (personality) ? intValue (personality) : -1, hasArg (difficulty) ? intValue (difficulty) : -1, hasArg (count) ? intValue (count) : -1);
|
||||
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
||||
int BotControl::cmdVote () {
|
||||
enum args { alias = 1, mapid, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, mapid };
|
||||
|
||||
if (!hasArg (mapid)) {
|
||||
return BotCommandResult::BadFormat;
|
||||
}
|
||||
int mapID = getInt (mapid);
|
||||
int mapID = intValue (mapid);
|
||||
|
||||
// loop through all players
|
||||
for (const auto &bot : bots) {
|
||||
|
|
@ -130,10 +122,7 @@ int BotControl::cmdVote () {
|
|||
}
|
||||
|
||||
int BotControl::cmdWeaponMode () {
|
||||
enum args { alias = 1, type, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, type };
|
||||
|
||||
if (!hasArg (type)) {
|
||||
return BotCommandResult::BadFormat;
|
||||
|
|
@ -148,7 +137,7 @@ int BotControl::cmdWeaponMode () {
|
|||
modes.push ("sniper", 6);
|
||||
modes.push ("standard", 7);
|
||||
|
||||
auto mode = getStr (type);
|
||||
auto mode = strValue (type);
|
||||
|
||||
// check if selected mode exists
|
||||
if (!modes.exists (mode)) {
|
||||
|
|
@ -160,32 +149,18 @@ int BotControl::cmdWeaponMode () {
|
|||
}
|
||||
|
||||
int BotControl::cmdVersion () {
|
||||
auto hash = String (PRODUCT_GIT_HASH).substr (0, 8);
|
||||
auto author = String (PRODUCT_GIT_COMMIT_AUTHOR);
|
||||
auto &build = product.build;
|
||||
|
||||
// if no hash specified, set local one
|
||||
if (hash.startsWith ("unspe")) {
|
||||
hash = "local";
|
||||
}
|
||||
|
||||
// if no commit author, set local one
|
||||
if (author.startsWith ("unspe")) {
|
||||
author = PRODUCT_EMAIL;
|
||||
}
|
||||
|
||||
msg ("%s v%s (build %u)", PRODUCT_NAME, PRODUCT_VERSION, util.buildNumber ());
|
||||
msg (" compiled: %s %s by %s", __DATE__, __TIME__, author.chars ());
|
||||
|
||||
if (!hash.startsWith ("local")) {
|
||||
msg (" commit: %scommit/%s", PRODUCT_COMMENTS, hash.chars ());
|
||||
}
|
||||
msg (" url: %s", PRODUCT_URL);
|
||||
msg ("%s v%s.%s (ID %s)", product.name, product.version, build.count, build.id);
|
||||
msg (" by %s (%s)", product.author, product.email);
|
||||
msg (" %s", product.url);
|
||||
msg ("compiled: %s on %s with %s", product.dtime, build.machine, build.compiler);
|
||||
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
||||
int BotControl::cmdNodeMenu () {
|
||||
enum args { alias = 1, max };
|
||||
enum args { alias = 1 };
|
||||
|
||||
// graph editor is available only with editor
|
||||
if (!graph.hasEditor ()) {
|
||||
|
|
@ -198,15 +173,12 @@ int BotControl::cmdNodeMenu () {
|
|||
}
|
||||
|
||||
int BotControl::cmdMenu () {
|
||||
enum args { alias = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, cmd };
|
||||
|
||||
// reset the current menu
|
||||
showMenu (Menu::None);
|
||||
|
||||
if (getStr (cmd) == "cmd" && util.isAlive (m_ent)) {
|
||||
if (strValue (cmd) == "cmd" && util.isAlive (m_ent)) {
|
||||
showMenu (Menu::Commands);
|
||||
}
|
||||
else {
|
||||
|
|
@ -216,28 +188,24 @@ int BotControl::cmdMenu () {
|
|||
}
|
||||
|
||||
int BotControl::cmdList () {
|
||||
enum args { alias = 1, max };
|
||||
enum args { alias = 1 };
|
||||
|
||||
bots.listBots ();
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
||||
int BotControl::cmdCvars () {
|
||||
enum args { alias = 1, pattern, max };
|
||||
enum args { alias = 1, pattern };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
|
||||
const auto &match = getStr (pattern);
|
||||
const auto &match = strValue (pattern);
|
||||
const bool isSave = match == "save";
|
||||
|
||||
File cfg;
|
||||
|
||||
// if save requested, dump cvars to yapb.cfg
|
||||
if (isSave) {
|
||||
cfg.open (strings.format ("%s/addons/yapb/conf/yapb.cfg", game.getModName ()), "wt");
|
||||
|
||||
cfg.puts ("// Configuration file for %s\n\n", PRODUCT_SHORT_NAME);
|
||||
cfg.open (strings.format ("%s/addons/%s/conf/%s.cfg", game.getModName (), product.folder, product.folder), "wt");
|
||||
cfg.puts ("// Configuration file for %s\n\n", product.name);
|
||||
}
|
||||
|
||||
for (const auto &cvar : game.getCvars ()) {
|
||||
|
|
@ -245,16 +213,16 @@ int BotControl::cmdCvars () {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!isSave && match != "empty" && !strstr (cvar.reg.name, match.chars ())) {
|
||||
if (!isSave && !match.empty () && !strstr (cvar.reg.name, match.chars ())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// float value ?
|
||||
bool isFloat = !strings.isEmpty (cvar.self->str ()) && strstr (cvar.self->str (), ".");
|
||||
bool isFloat = !strings.isEmpty (cvar.self->str ()) && strchr (cvar.self->str (), '.');
|
||||
|
||||
if (isSave) {
|
||||
cfg.puts ("//\n");
|
||||
cfg.puts ("// %s\n", String::join (cvar.info.split ("\n"), "\n// ").chars ());
|
||||
cfg.puts ("// %s\n", String::join (cvar.info.split ("\n"), "\n// "));
|
||||
cfg.puts ("// ---\n");
|
||||
|
||||
if (cvar.bounded) {
|
||||
|
|
@ -285,7 +253,7 @@ int BotControl::cmdCvars () {
|
|||
}
|
||||
else {
|
||||
game.print ("cvar: %s", cvar.reg.name);
|
||||
game.print ("info: %s", cvar.info.chars ());
|
||||
game.print ("info: %s", cvar.info);
|
||||
|
||||
game.print (" ");
|
||||
}
|
||||
|
|
@ -299,13 +267,10 @@ int BotControl::cmdCvars () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNode () {
|
||||
enum args { root, alias, cmd, cmd2, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { root, alias, cmd, cmd2 };
|
||||
|
||||
// graph editor supported only with editor
|
||||
if (game.isDedicated () && !graph.hasEditor () && getStr (cmd) != "acquire_editor") {
|
||||
if (game.isDedicated () && !graph.hasEditor () && strValue (cmd) != "acquire_editor") {
|
||||
msg ("Unable to use graph edit commands without setting graph editor player. Please use \"graph acquire_editor\" to acquire rights for graph editing.");
|
||||
return BotCommandResult::Handled;
|
||||
}
|
||||
|
|
@ -318,68 +283,68 @@ int BotControl::cmdNode () {
|
|||
if (descriptions.empty ()) {
|
||||
|
||||
// separate function
|
||||
auto pushGraphCmd = [&] (String cmd, String format, String help, Handler handler) -> void {
|
||||
BotCmd botCmd (cr::move (cmd), cr::move (format), cr::move (help), cr::move (handler));
|
||||
auto addGraphCmd = [&] (String cmd, String format, String help, Handler handler) -> void {
|
||||
BotCmd botCmd { cmd, cr::move (format), cr::move (help), cr::move (handler) };
|
||||
|
||||
commands.push (cmd, cr::move (botCmd));
|
||||
descriptions.push (cmd);
|
||||
};
|
||||
|
||||
// add graph commands
|
||||
pushGraphCmd ("on", "on [display|auto|noclip|models]", "Enables displaying of graph, nodes, noclip cheat", &BotControl::cmdNodeOn);
|
||||
pushGraphCmd ("off", "off [display|auto|noclip|models]", "Disables displaying of graph, auto adding nodes, noclip cheat", &BotControl::cmdNodeOff);
|
||||
pushGraphCmd ("menu", "menu [noarguments]", "Opens and displays bots graph edtior.", &BotControl::cmdNodeMenu);
|
||||
pushGraphCmd ("add", "add [noarguments]", "Opens and displays graph node add menu.", &BotControl::cmdNodeAdd);
|
||||
pushGraphCmd ("addbasic", "menu [noarguments]", "Adds basic nodes such as player spawn points, goals and ladders.", &BotControl::cmdNodeAddBasic);
|
||||
pushGraphCmd ("save", "save [noarguments]", "Save graph file to disk.", &BotControl::cmdNodeSave);
|
||||
pushGraphCmd ("load", "load [noarguments]", "Load graph file from disk.", &BotControl::cmdNodeLoad);
|
||||
pushGraphCmd ("erase", "erase [iamsure]", "Erases the graph file from disk.", &BotControl::cmdNodeErase);
|
||||
pushGraphCmd ("delete", "delete [nearest|index]", "Deletes single graph node from map.", &BotControl::cmdNodeDelete);
|
||||
pushGraphCmd ("check", "check [noarguments]", "Check if graph working correctly.", &BotControl::cmdNodeCheck);
|
||||
pushGraphCmd ("cache", "cache [nearest|index]", "Caching node for future use.", &BotControl::cmdNodeCache);
|
||||
pushGraphCmd ("clean", "clean [all|nearest|index]", "Clean useless path connections from all or single node.", &BotControl::cmdNodeClean);
|
||||
pushGraphCmd ("setradius", "setradius [radius] [nearest|index]", "Sets the radius for node.", &BotControl::cmdNodeSetRadius);
|
||||
pushGraphCmd ("flags", "flags [noarguments]", "Open and displays menu for modifying flags for nearest point.", &BotControl::cmdNodeSetFlags);
|
||||
pushGraphCmd ("teleport", "teleport [index]", "Teleports player to specified node index.", &BotControl::cmdNodeTeleport);
|
||||
pushGraphCmd ("upload", "upload [id]", "Uploads created graph to graph database.", &BotControl::cmdNodeUpload);
|
||||
addGraphCmd ("on", "on [display|auto|noclip|models]", "Enables displaying of graph, nodes, noclip cheat", &BotControl::cmdNodeOn);
|
||||
addGraphCmd ("off", "off [display|auto|noclip|models]", "Disables displaying of graph, auto adding nodes, noclip cheat", &BotControl::cmdNodeOff);
|
||||
addGraphCmd ("menu", "menu [noarguments]", "Opens and displays bots graph edtior.", &BotControl::cmdNodeMenu);
|
||||
addGraphCmd ("add", "add [noarguments]", "Opens and displays graph node add menu.", &BotControl::cmdNodeAdd);
|
||||
addGraphCmd ("addbasic", "menu [noarguments]", "Adds basic nodes such as player spawn points, goals and ladders.", &BotControl::cmdNodeAddBasic);
|
||||
addGraphCmd ("save", "save [noarguments]", "Save graph file to disk.", &BotControl::cmdNodeSave);
|
||||
addGraphCmd ("load", "load [noarguments]", "Load graph file from disk.", &BotControl::cmdNodeLoad);
|
||||
addGraphCmd ("erase", "erase [iamsure]", "Erases the graph file from disk.", &BotControl::cmdNodeErase);
|
||||
addGraphCmd ("delete", "delete [nearest|index]", "Deletes single graph node from map.", &BotControl::cmdNodeDelete);
|
||||
addGraphCmd ("check", "check [noarguments]", "Check if graph working correctly.", &BotControl::cmdNodeCheck);
|
||||
addGraphCmd ("cache", "cache [nearest|index]", "Caching node for future use.", &BotControl::cmdNodeCache);
|
||||
addGraphCmd ("clean", "clean [all|nearest|index]", "Clean useless path connections from all or single node.", &BotControl::cmdNodeClean);
|
||||
addGraphCmd ("setradius", "setradius [radius] [nearest|index]", "Sets the radius for node.", &BotControl::cmdNodeSetRadius);
|
||||
addGraphCmd ("flags", "flags [noarguments]", "Open and displays menu for modifying flags for nearest point.", &BotControl::cmdNodeSetFlags);
|
||||
addGraphCmd ("teleport", "teleport [index]", "Teleports player to specified node index.", &BotControl::cmdNodeTeleport);
|
||||
addGraphCmd ("upload", "upload [id]", "Uploads created graph to graph database.", &BotControl::cmdNodeUpload);
|
||||
|
||||
// add path commands
|
||||
pushGraphCmd ("path_create", "path_create [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
pushGraphCmd ("path_create_in", "path_create_in [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
pushGraphCmd ("path_create_out", "path_create_out [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
pushGraphCmd ("path_create_both", "path_create_both [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
pushGraphCmd ("path_delete", "path_create_both [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathDelete);
|
||||
pushGraphCmd ("path_set_autopath", "path_set_autoath [max_distance]", "Opens and displays path creation menu.", &BotControl::cmdNodePathSetAutoDistance);
|
||||
addGraphCmd ("path_create", "path_create [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
addGraphCmd ("path_create_in", "path_create_in [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
addGraphCmd ("path_create_out", "path_create_out [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
addGraphCmd ("path_create_both", "path_create_both [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
|
||||
addGraphCmd ("path_delete", "path_create_both [noarguments]", "Opens and displays path deletion menu.", &BotControl::cmdNodePathDelete);
|
||||
addGraphCmd ("path_set_autopath", "path_set_autopath [max_distance]", "Opens and displays path creation menu.", &BotControl::cmdNodePathSetAutoDistance);
|
||||
|
||||
// camp points iterator
|
||||
pushGraphCmd ("iterate_camp", "iterate_camp [begin|end|next]", "Allows to go through all camp points on map.", &BotControl::cmdNodeIterateCamp);
|
||||
addGraphCmd ("iterate_camp", "iterate_camp [begin|end|next]", "Allows to go through all camp points on map.", &BotControl::cmdNodeIterateCamp);
|
||||
|
||||
// remote graph editing stuff
|
||||
if (game.isDedicated ()) {
|
||||
pushGraphCmd ("acquire_editor", "acquire_editor [max_distance]", "Acquires rights to edit graph on dedicated server.", &BotControl::cmdNodeAcquireEditor);
|
||||
pushGraphCmd ("release_editor", "acquire_editor [max_distance]", "Releases graph editing rights.", &BotControl::cmdNodeAcquireEditor);
|
||||
addGraphCmd ("acquire_editor", "acquire_editor", "Acquires rights to edit graph on dedicated server.", &BotControl::cmdNodeAcquireEditor);
|
||||
addGraphCmd ("release_editor", "acquire_editor", "Releases graph editing rights.", &BotControl::cmdNodeAcquireEditor);
|
||||
}
|
||||
}
|
||||
if (commands.exists (getStr (cmd))) {
|
||||
auto item = commands[getStr (cmd)];
|
||||
if (commands.exists (strValue (cmd))) {
|
||||
auto item = commands[strValue (cmd)];
|
||||
|
||||
// graph have only bad format return status
|
||||
int status = (this->*item.handler) ();
|
||||
|
||||
if (status == BotCommandResult::BadFormat) {
|
||||
msg ("Incorrect usage of \"%s %s %s\" command. Correct usage is:\n\n\t%s\n\nPlease use correct format.", m_args[root].chars (), m_args[alias].chars (), item.name.chars (), item.format.chars ());
|
||||
msg ("Incorrect usage of \"%s %s %s\" command. Correct usage is:\n\n\t%s\n\nPlease use correct format.", m_args[root], m_args[alias], item.name, item.format);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (getStr (cmd) == "help" && hasArg (cmd2) && commands.exists (getStr (cmd2))) {
|
||||
auto &item = commands[getStr (cmd2)];
|
||||
if (strValue (cmd) == "help" && hasArg (cmd2) && commands.exists (strValue (cmd2))) {
|
||||
auto &item = commands[strValue (cmd2)];
|
||||
|
||||
msg ("Command: \"%s %s %s\"\nFormat: %s\nHelp: %s", m_args[root].chars (), m_args[alias].chars (), item.name.chars (), item.format.chars (), item.help.chars ());
|
||||
msg ("Command: \"%s %s %s\"\nFormat: %s\nHelp: %s", m_args[root], m_args[alias], item.name, item.format, item.help);
|
||||
}
|
||||
else {
|
||||
for (auto &desc : descriptions) {
|
||||
auto &item = commands[desc];
|
||||
msg (" %s - %s", item.name.chars (), item.help.chars ());
|
||||
msg (" %s - %s", item.name, item.help);
|
||||
}
|
||||
msg ("Currently Graph Status %s", graph.hasEditFlag (GraphEdit::On) ? "Enabled" : "Disabled");
|
||||
}
|
||||
|
|
@ -388,19 +353,16 @@ int BotControl::cmdNode () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeOn () {
|
||||
enum args { alias = 1, cmd, option, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { alias = 1, cmd, option };
|
||||
|
||||
// enable various features of editor
|
||||
if (getStr (option) == "empty" || getStr (option) == "display" || getStr (option) == "models") {
|
||||
if (strValue (option).empty () || strValue (option) == "display" || strValue (option) == "models") {
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
enableDrawModels (true);
|
||||
|
||||
msg ("Graph editor has been enabled.");
|
||||
}
|
||||
else if (getStr (option) == "noclip") {
|
||||
else if (strValue (option) == "noclip") {
|
||||
m_ent->v.movetype = MOVETYPE_NOCLIP;
|
||||
|
||||
graph.setEditFlag (GraphEdit::On | GraphEdit::Noclip);
|
||||
|
|
@ -408,7 +370,7 @@ int BotControl::cmdNodeOn () {
|
|||
|
||||
msg ("Graph editor has been enabled with noclip mode.");
|
||||
}
|
||||
else if (getStr (option) == "auto") {
|
||||
else if (strValue (option) == "auto") {
|
||||
graph.setEditFlag (GraphEdit::On | GraphEdit::Auto);
|
||||
enableDrawModels (true);
|
||||
|
||||
|
|
@ -426,30 +388,27 @@ int BotControl::cmdNodeOn () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeOff () {
|
||||
enum args { graph_cmd = 1, cmd, option, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, option };
|
||||
|
||||
// enable various features of editor
|
||||
if (getStr (option) == "empty" || getStr (option) == "display") {
|
||||
if (strValue (option).empty () || strValue (option) == "display") {
|
||||
graph.clearEditFlag (GraphEdit::On | GraphEdit::Auto | GraphEdit::Noclip);
|
||||
enableDrawModels (false);
|
||||
|
||||
msg ("Graph editor has been disabled.");
|
||||
}
|
||||
else if (getStr (option) == "models") {
|
||||
else if (strValue (option) == "models") {
|
||||
enableDrawModels (false);
|
||||
|
||||
msg ("Graph editor has disabled spawn points highlighting.");
|
||||
}
|
||||
else if (getStr (option) == "noclip") {
|
||||
else if (strValue (option) == "noclip") {
|
||||
m_ent->v.movetype = MOVETYPE_WALK;
|
||||
graph.clearEditFlag (GraphEdit::Noclip);
|
||||
|
||||
msg ("Graph editor has disabled noclip mode.");
|
||||
}
|
||||
else if (getStr (option) == "auto") {
|
||||
else if (strValue (option) == "auto") {
|
||||
graph.clearEditFlag (GraphEdit::Auto);
|
||||
msg ("Graph editor has disabled auto add node mode.");
|
||||
}
|
||||
|
|
@ -457,10 +416,7 @@ int BotControl::cmdNodeOff () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeAdd () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
|
@ -471,11 +427,7 @@ int BotControl::cmdNodeAdd () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeAddBasic () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
|
|
@ -486,18 +438,15 @@ int BotControl::cmdNodeAddBasic () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeSave () {
|
||||
enum args { graph_cmd = 1, cmd, option, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, option };
|
||||
|
||||
// if no check is set save anyway
|
||||
if (getStr (option) == "nocheck") {
|
||||
if (strValue (option) == "nocheck") {
|
||||
graph.saveGraphData ();
|
||||
|
||||
msg ("All nodes has been saved and written to disk (IGNORING QUALITY CONTROL).");
|
||||
}
|
||||
else if (getStr (option) == "old") {
|
||||
else if (strValue (option) == "old") {
|
||||
graph.saveOldFormat ();
|
||||
|
||||
msg ("All nodes has been saved and written to disk (POD-Bot Format (.pwf)).");
|
||||
|
|
@ -515,10 +464,7 @@ int BotControl::cmdNodeSave () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeLoad () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// just save graph on request
|
||||
if (graph.loadGraphData ()) {
|
||||
|
|
@ -531,13 +477,10 @@ int BotControl::cmdNodeLoad () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeErase () {
|
||||
enum args { graph_cmd = 1, cmd, iamsure, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, iamsure };
|
||||
|
||||
// prevent accidents when graph are deleted unintentionally
|
||||
if (getStr (iamsure) == "iamsure") {
|
||||
if (strValue (iamsure) == "iamsure") {
|
||||
graph.eraseFromDisk ();
|
||||
}
|
||||
else {
|
||||
|
|
@ -547,20 +490,17 @@ int BotControl::cmdNodeErase () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeDelete () {
|
||||
enum args { graph_cmd = 1, cmd, nearest, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, nearest };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
// if "neareset" or nothing passed delete neareset, else delete by index
|
||||
if (getStr (nearest) == "empty" || getStr (nearest) == "nearest") {
|
||||
if (strValue (nearest).empty () || strValue (nearest) == "nearest") {
|
||||
graph.erase (kInvalidNodeIndex);
|
||||
}
|
||||
else {
|
||||
int index = getInt (nearest);
|
||||
int index = intValue (nearest);
|
||||
|
||||
// check for existence
|
||||
if (graph.exists (index)) {
|
||||
|
|
@ -575,10 +515,7 @@ int BotControl::cmdNodeDelete () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeCheck () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// check if nodes are ok
|
||||
if (graph.checkNodes (true)) {
|
||||
|
|
@ -588,22 +525,19 @@ int BotControl::cmdNodeCheck () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeCache () {
|
||||
enum args { graph_cmd = 1, cmd, nearest, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, nearest };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
// if "neareset" or nothing passed delete neareset, else delete by index
|
||||
if (getStr (nearest) == "empty" || getStr (nearest) == "nearest") {
|
||||
if (strValue (nearest).empty () || strValue (nearest) == "nearest") {
|
||||
graph.cachePoint (kInvalidNodeIndex);
|
||||
|
||||
msg ("Nearest node has been put into the memory.");
|
||||
}
|
||||
else {
|
||||
int index = getInt (nearest);
|
||||
int index = intValue (nearest);
|
||||
|
||||
// check for existence
|
||||
if (graph.exists (index)) {
|
||||
|
|
@ -618,16 +552,13 @@ int BotControl::cmdNodeCache () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeClean () {
|
||||
enum args { graph_cmd = 1, cmd, option, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, option };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
// if "all" passed clean up all the paths
|
||||
if (getStr (option) == "all") {
|
||||
if (strValue (option) == "all") {
|
||||
int removed = 0;
|
||||
|
||||
for (int i = 0; i < graph.length (); ++i) {
|
||||
|
|
@ -635,13 +566,13 @@ int BotControl::cmdNodeClean () {
|
|||
}
|
||||
msg ("Done. Processed %d nodes. %d useless paths was cleared.", graph.length (), removed);
|
||||
}
|
||||
else if (getStr (option) == "empty" || getStr (option) == "nearest") {
|
||||
else if (strValue (option).empty () || strValue (option) == "nearest") {
|
||||
int removed = graph.clearConnections (graph.getEditorNeareset ());
|
||||
|
||||
msg ("Done. Processed node %d. %d useless paths was cleared.", graph.getEditorNeareset (), removed);
|
||||
}
|
||||
else {
|
||||
int index = getInt (option);
|
||||
int index = intValue (option);
|
||||
|
||||
// check for existence
|
||||
if (graph.exists (index)) {
|
||||
|
|
@ -657,10 +588,7 @@ int BotControl::cmdNodeClean () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeSetRadius () {
|
||||
enum args { graph_cmd = 1, cmd, radius, index, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, radius, index };
|
||||
|
||||
// radius is a must
|
||||
if (!hasArg (radius)) {
|
||||
|
|
@ -668,13 +596,13 @@ int BotControl::cmdNodeSetRadius () {
|
|||
}
|
||||
int radiusIndex = kInvalidNodeIndex;
|
||||
|
||||
if (getStr (index) == "empty" || getStr (index) == "nearest") {
|
||||
if (strValue (index).empty () || strValue (index) == "nearest") {
|
||||
radiusIndex = graph.getEditorNeareset ();
|
||||
}
|
||||
else {
|
||||
radiusIndex = getInt (index);
|
||||
radiusIndex = intValue (index);
|
||||
}
|
||||
float value = getStr (radius).float_ ();
|
||||
float value = strValue (radius).float_ ();
|
||||
|
||||
graph.setRadius (radiusIndex, value);
|
||||
msg ("Node %d has been set to radius %.2f.", radiusIndex, value);
|
||||
|
|
@ -683,10 +611,7 @@ int BotControl::cmdNodeSetRadius () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeSetFlags () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
|
@ -697,15 +622,12 @@ int BotControl::cmdNodeSetFlags () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeTeleport () {
|
||||
enum args { graph_cmd = 1, cmd, teleport_index, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, teleport_index };
|
||||
|
||||
if (!hasArg (teleport_index)) {
|
||||
return BotCommandResult::BadFormat;
|
||||
}
|
||||
int index = getInt (teleport_index);
|
||||
int index = intValue (teleport_index);
|
||||
|
||||
// check for existence
|
||||
if (graph.exists (index)) {
|
||||
|
|
@ -723,22 +645,19 @@ int BotControl::cmdNodeTeleport () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodePathCreate () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
// choose the direction for path creation
|
||||
if (m_args[cmd].find ("_both", 0) != String::InvalidIndex) {
|
||||
if (strValue (cmd).find ("_both", 0) != String::InvalidIndex) {
|
||||
graph.pathCreate (PathConnection::Bidirectional);
|
||||
}
|
||||
else if (m_args[cmd].find ("_in", 0) != String::InvalidIndex) {
|
||||
else if (strValue (cmd).find ("_in", 0) != String::InvalidIndex) {
|
||||
graph.pathCreate (PathConnection::Incoming);
|
||||
}
|
||||
else if (m_args[cmd].find ("_out", 0) != String::InvalidIndex) {
|
||||
else if (strValue (cmd).find ("_out", 0) != String::InvalidIndex) {
|
||||
graph.pathCreate (PathConnection::Outgoing);
|
||||
}
|
||||
else {
|
||||
|
|
@ -748,10 +667,7 @@ int BotControl::cmdNodePathCreate () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodePathDelete () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
|
@ -763,10 +679,7 @@ int BotControl::cmdNodePathDelete () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodePathSetAutoDistance () {
|
||||
enum args { graph_cmd = 1, cmd, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
|
@ -776,10 +689,7 @@ int BotControl::cmdNodePathSetAutoDistance () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeAcquireEditor () {
|
||||
enum args { graph_cmd = 1, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1 };
|
||||
|
||||
if (game.isNullEntity (m_ent)) {
|
||||
msg ("This command should not be executed from HLDS console.");
|
||||
|
|
@ -797,10 +707,7 @@ int BotControl::cmdNodeAcquireEditor () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeReleaseEditor () {
|
||||
enum args { graph_cmd = 1, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1 };
|
||||
|
||||
if (!graph.hasEditor ()) {
|
||||
msg ("No one is currently has rights to edit. Nothing to release.");
|
||||
|
|
@ -831,9 +738,9 @@ int BotControl::cmdNodeUpload () {
|
|||
http.setTimeout (6);
|
||||
|
||||
// try to upload the file
|
||||
if (http.uploadFile ("http://upload.ubot.su/", strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), game.getMapName ()))) {
|
||||
msg ("Graph file was successfully validated and uploaded to the Ubot S3 storage (https://dl.ubot.su/).");
|
||||
msg ("It will be available for download for all Ubot and YaPB users in a few minutes");
|
||||
if (http.uploadFile ("http://yapb.ru/graph", strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), game.getMapName ()))) {
|
||||
msg ("Graph file was successfully validated and uploaded to the YaPB Graph DB (%s).", product.download);
|
||||
msg ("It will be available for download for all YaPB users in a few minutes.");
|
||||
msg ("\n");
|
||||
msg ("Thank you.");
|
||||
msg ("\n");
|
||||
|
|
@ -851,7 +758,7 @@ int BotControl::cmdNodeUpload () {
|
|||
else {
|
||||
status.assignf ("%d", code);
|
||||
}
|
||||
msg ("Something went wrong with uploading. Come back later. (%s)", status.chars ());
|
||||
msg ("Something went wrong with uploading. Come back later. (%s)", status);
|
||||
msg ("\n");
|
||||
|
||||
if (code == HttpClientResult::Forbidden) {
|
||||
|
|
@ -868,16 +775,13 @@ int BotControl::cmdNodeUpload () {
|
|||
}
|
||||
|
||||
int BotControl::cmdNodeIterateCamp () {
|
||||
enum args { graph_cmd = 1, cmd, option, max };
|
||||
|
||||
// adding more args to args array, if not enough passed
|
||||
fixMissingArgs (max);
|
||||
enum args { graph_cmd = 1, cmd, option };
|
||||
|
||||
// turn graph on
|
||||
graph.setEditFlag (GraphEdit::On);
|
||||
|
||||
// get the option descriping operation
|
||||
auto op = getStr (option);
|
||||
auto op = strValue (option);
|
||||
|
||||
if (op != "begin" && op != "end" && op != "next") {
|
||||
return BotCommandResult::BadFormat;
|
||||
|
|
@ -973,8 +877,8 @@ int BotControl::menuFeatures (int item) {
|
|||
break;
|
||||
|
||||
case 4:
|
||||
extern ConVar yb_debug;
|
||||
yb_debug.set (yb_debug.int_ () ^ 1);
|
||||
extern ConVar cv_debug;
|
||||
cv_debug.set (cv_debug.int_ () ^ 1);
|
||||
|
||||
showMenu (Menu::Features);
|
||||
break;
|
||||
|
|
@ -1646,18 +1550,14 @@ bool BotControl::executeCommands () {
|
|||
if (m_args.empty ()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// handle only "yb" and "yapb" commands
|
||||
if (m_args[0] != "yb" && m_args[0] != "yapb") {
|
||||
return false;
|
||||
}
|
||||
Client &client = util.getClient (game.indexOfPlayer (m_ent));
|
||||
|
||||
// do not allow to execute stuff for non admins
|
||||
if (m_ent != game.getLocalEntity () && !(client.flags & ClientFlags::Admin)) {
|
||||
msg ("Access to %s commands is restricted.", PRODUCT_SHORT_NAME);
|
||||
msg ("Access to %s commands is restricted.", product.name);
|
||||
return true;
|
||||
}
|
||||
const auto &prefix = m_args[0];
|
||||
|
||||
auto aliasMatch = [] (String &test, const String &cmd, String &aliasName) -> bool {
|
||||
for (auto &alias : test.split ("/")) {
|
||||
|
|
@ -1671,18 +1571,11 @@ bool BotControl::executeCommands () {
|
|||
String cmd;
|
||||
|
||||
// give some help
|
||||
if (m_args.length () > 0 && m_args[1] == "help") {
|
||||
if (hasArg (1) && m_args[1] == "help") {
|
||||
for (auto &item : m_cmds) {
|
||||
if (aliasMatch (item.name, m_args[2], cmd)) {
|
||||
msg ("Command: \"%s %s\"\nFormat: %s\nHelp: %s", m_args[0].chars (), cmd.chars (), item.format.chars (), item.help.chars ());
|
||||
|
||||
String aliases;
|
||||
|
||||
for (auto &alias : item.name.split ("/")) {
|
||||
aliases.appendf ("%s, ", alias.chars ());
|
||||
}
|
||||
aliases.rtrim (", ");
|
||||
msg ("Aliases: %s", aliases.chars ());
|
||||
msg ("Command: \"%s %s\"\nFormat: %s\nHelp: %s", prefix, cmd, item.format, item.help);
|
||||
msg ("Aliases: %s", String::join (item.name.split ("/"), ", "));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1692,7 +1585,7 @@ bool BotControl::executeCommands () {
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
msg ("No help found for \"%s\"", m_args[2].chars ());
|
||||
msg ("No help found for \"%s\"", m_args[2]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1700,33 +1593,29 @@ bool BotControl::executeCommands () {
|
|||
|
||||
// if no args passed just print all the commands
|
||||
if (m_args.length () == 1) {
|
||||
msg ("usage %s <command> [arguments]", m_args[0].chars ());
|
||||
msg ("usage %s <command> [arguments]", prefix);
|
||||
msg ("valid commands are: ");
|
||||
|
||||
for (auto &item : m_cmds) {
|
||||
msg (" %s - %s", item.name.split ("/")[0].chars (), item.help.chars ());
|
||||
msg (" %s - %s", item.name.split ("/")[0], item.help);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// first search for a actual cmd
|
||||
for (auto &item : m_cmds) {
|
||||
auto root = m_args[0].chars ();
|
||||
|
||||
if (aliasMatch (item.name, m_args[1], cmd)) {
|
||||
auto alias = cmd.chars ();
|
||||
|
||||
switch ((this->*item.handler) ()) {
|
||||
case BotCommandResult::Handled:
|
||||
default:
|
||||
break;
|
||||
|
||||
case BotCommandResult::ListenServer:
|
||||
msg ("Command \"%s %s\" is only available from the listenserver console.", root, alias);
|
||||
msg ("Command \"%s %s\" is only available from the listenserver console.", prefix, cmd);
|
||||
break;
|
||||
|
||||
case BotCommandResult::BadFormat:
|
||||
msg ("Incorrect usage of \"%s %s\" command. Correct usage is:\n\n\t%s\n\nPlease type \"%s help %s\" to get more information.", root, alias, item.format.chars (), root, alias);
|
||||
msg ("Incorrect usage of \"%s %s\" command. Correct usage is:\n\n\t%s\n\nPlease type \"%s help %s\" to get more information.", prefix, cmd, item.format, prefix, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1734,7 +1623,11 @@ bool BotControl::executeCommands () {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
msg ("Unrecognized command: %s", m_args[1].chars ());
|
||||
msg ("Unknown command: %s", m_args[1]);
|
||||
|
||||
// clear all the arguments upon finish
|
||||
m_args.clear ();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1745,14 +1638,14 @@ bool BotControl::executeMenus () {
|
|||
auto &issuer = util.getClient (game.indexOfPlayer (m_ent));
|
||||
|
||||
// check if it's menu select, and some key pressed
|
||||
if (getStr (0) != "menuselect" || getStr (1).empty () || issuer.menu == Menu::None) {
|
||||
if (strValue (0) != "menuselect" || strValue (1).empty () || issuer.menu == Menu::None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// let's get handle
|
||||
for (auto &menu : m_menus) {
|
||||
if (menu.ident == issuer.menu) {
|
||||
return (this->*menu.handler) (getStr (1).int_ ());
|
||||
return (this->*menu.handler) (strValue (1).int_ ());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1764,7 +1657,7 @@ void BotControl::showMenu (int id) {
|
|||
// make menus looks like we need only once
|
||||
if (!s_menusParsed) {
|
||||
for (auto &parsed : m_menus) {
|
||||
const String &translated = conf.translate (parsed.text.chars ());
|
||||
StringRef translated = conf.translate (parsed.text);
|
||||
|
||||
// translate all the things
|
||||
parsed.text = translated;
|
||||
|
|
@ -1797,7 +1690,7 @@ void BotControl::showMenu (int id) {
|
|||
|
||||
for (auto &display : m_menus) {
|
||||
if (display.ident == id) {
|
||||
auto text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !yb_display_menu_text.bool_ ()) ? " " : display.text.chars ();
|
||||
auto text = (game.is (GameFlags::Xash3D | GameFlags::Mobility) && !cv_display_menu_text.bool_ ()) ? " " : display.text.chars ();
|
||||
MessageWriter msg;
|
||||
|
||||
while (strlen (text) >= 64) {
|
||||
|
|
@ -1870,8 +1763,8 @@ void BotControl::assignAdminRights (edict_t *ent, char *infobuffer) {
|
|||
if (!game.isDedicated () || util.isFakeClient (ent)) {
|
||||
return;
|
||||
}
|
||||
const String &key = yb_password_key.str ();
|
||||
const String &password = yb_password.str ();
|
||||
StringRef key = cv_password_key.str ();
|
||||
StringRef password = cv_password.str ();
|
||||
|
||||
if (!key.empty () && !password.empty ()) {
|
||||
auto &client = util.getClient (game.indexOfPlayer (ent));
|
||||
|
|
@ -1898,18 +1791,18 @@ void BotControl::maintainAdminRights () {
|
|||
Client &client = util.getClient (i);
|
||||
|
||||
if (client.flags & ClientFlags::Admin) {
|
||||
if (strings.isEmpty (yb_password_key.str ()) && strings.isEmpty (yb_password.str ())) {
|
||||
if (strings.isEmpty (cv_password_key.str ()) && strings.isEmpty (cv_password.str ())) {
|
||||
client.flags &= ~ClientFlags::Admin;
|
||||
}
|
||||
else if (!!strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ())))) {
|
||||
else if (!!strcmp (cv_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (cv_password_key.str ())))) {
|
||||
client.flags &= ~ClientFlags::Admin;
|
||||
game.print ("Player %s had lost remote access to %s.", player->v.netname.chars (), PRODUCT_SHORT_NAME);
|
||||
game.print ("Player %s had lost remote access to %s.", player->v.netname.chars (), product.name);
|
||||
}
|
||||
}
|
||||
else if (!(client.flags & ClientFlags::Admin) && !strings.isEmpty (yb_password_key.str ()) && !strings.isEmpty (yb_password.str ())) {
|
||||
if (strcmp (yb_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (yb_password_key.str ()))) == 0) {
|
||||
else if (!(client.flags & ClientFlags::Admin) && !strings.isEmpty (cv_password_key.str ()) && !strings.isEmpty (cv_password.str ())) {
|
||||
if (strcmp (cv_password.str (), engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (client.ent), const_cast <char *> (cv_password_key.str ()))) == 0) {
|
||||
client.flags |= ClientFlags::Admin;
|
||||
game.print ("Player %s had gained full remote access to %s.", player->v.netname.chars (), PRODUCT_SHORT_NAME);
|
||||
game.print ("Player %s had gained full remote access to %s.", player->v.netname.chars (), product.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,25 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_csdm_mode ("yb_csdm_mode", "0", "Enables or disables CSDM / FFA mode for bots.\nAllowed values: '0', '1', '2', '3'.\nIf '0', CSDM / FFA mode is auto-detected.\nIf '1', CSDM mode is enabled, but FFA is disabled.\nIf '2' CSDM and FFA mode is enabled.\nIf '3' CSDM and FFA mode is disabled.", true, 0.0f, 3.0f);
|
||||
ConVar cv_csdm_mode ("ub_csdm_mode", "0", "Enables or disables CSDM / FFA mode for bots.\nAllowed values: '0', '1', '2', '3'.\nIf '0', CSDM / FFA mode is auto-detected.\nIf '1', CSDM mode is enabled, but FFA is disabled.\nIf '2' CSDM and FFA mode is enabled.\nIf '3' CSDM and FFA mode is disabled.", true, 0.0f, 3.0f);
|
||||
|
||||
ConVar sv_skycolor_r ("sv_skycolor_r", nullptr, Var::NoRegister);
|
||||
ConVar sv_skycolor_g ("sv_skycolor_g", nullptr, Var::NoRegister);
|
||||
ConVar sv_skycolor_b ("sv_skycolor_b", nullptr, Var::NoRegister);
|
||||
ConVar sv_skycolor_r ("sv_skycolor_r", nullptr, Var::GameRef);
|
||||
ConVar sv_skycolor_g ("sv_skycolor_g", nullptr, Var::GameRef);
|
||||
ConVar sv_skycolor_b ("sv_skycolor_b", nullptr, Var::GameRef);
|
||||
|
||||
Game::Game () {
|
||||
m_startEntity = nullptr;
|
||||
|
|
@ -64,12 +71,15 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
|||
// clear all breakables before initialization
|
||||
m_breakables.clear ();
|
||||
|
||||
// precache everything
|
||||
precache ();
|
||||
|
||||
// go thru the all entities on map, and do whatever we're want
|
||||
for (int i = 0; i < max; ++i) {
|
||||
auto ent = entities + i;
|
||||
|
||||
// only valid entities
|
||||
if (!ent || ent->free || ent->v.classname == 0) {
|
||||
if (!ent || ent->v.classname == 0) {
|
||||
continue;
|
||||
}
|
||||
auto classname = ent->v.classname.chars ();
|
||||
|
|
@ -109,7 +119,6 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
|||
|
||||
++m_spawnCount[Team::Terrorist];
|
||||
}
|
||||
|
||||
else if (strcmp (classname, "info_vip_start") == 0) {
|
||||
m_engineWrap.setModel (ent, "models/player/vip/vip.mdl");
|
||||
|
||||
|
|
@ -191,7 +200,7 @@ void Game::testLine (const Vector &start, const Vector &end, int ignoreFlags, ed
|
|||
// whether the trace starts "inside" an entity's polygonal model, and if so, to specify that entity
|
||||
// in ignoreEntity in order to ignore it as a possible obstacle.
|
||||
|
||||
int engineFlags = 0;
|
||||
auto engineFlags = 0;
|
||||
|
||||
if (ignoreFlags & TraceIgnore::Monsters) {
|
||||
engineFlags = 1;
|
||||
|
|
@ -203,6 +212,35 @@ void Game::testLine (const Vector &start, const Vector &end, int ignoreFlags, ed
|
|||
engfuncs.pfnTraceLine (start, end, engineFlags, ignoreEntity, ptr);
|
||||
}
|
||||
|
||||
bool Game::testLineChannel (TraceChannel channel, const Vector &start, const Vector &end, int ignoreFlags, edict_t *ignoreEntity, TraceResult *ptr) {
|
||||
// this function traces a line dot by dot, starting from vecStart in the direction of vecEnd,
|
||||
// ignoring or not monsters (depending on the value of IGNORE_MONSTERS, true or false), and stops
|
||||
// at the first obstacle encountered, returning the results of the trace in the TraceResult structure
|
||||
// ptr. Such results are (amongst others) the distance traced, the hit surface, the hit plane
|
||||
// vector normal, etc. See the TraceResult structure for details. This function allows to specify
|
||||
// whether the trace starts "inside" an entity's polygonal model, and if so, to specify that entity
|
||||
// in ignoreEntity in order to ignore it as a possible obstacle.
|
||||
|
||||
auto bot = bots[ignoreEntity];
|
||||
|
||||
// check if bot is firing trace line
|
||||
if (bot && bot->canSkipNextTrace (channel)) {
|
||||
ptr = bot->getLastTraceResult (channel); // set the result from bot stored one
|
||||
|
||||
// current call is skipped
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
testLine (start, end, ignoreFlags, ignoreEntity, ptr);
|
||||
|
||||
// if we're still reaching here, save the last trace result
|
||||
if (bot) {
|
||||
bot->setLastTraceResult (channel, ptr);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::testHull (const Vector &start, const Vector &end, int ignoreFlags, int hullNumber, edict_t *ignoreEntity, TraceResult *ptr) {
|
||||
// this function traces a hull dot by dot, starting from vecStart in the direction of vecEnd,
|
||||
// ignoring or not monsters (depending on the value of IGNORE_MONSTERS, true or
|
||||
|
|
@ -219,8 +257,7 @@ void Game::testHull (const Vector &start, const Vector &end, int ignoreFlags, in
|
|||
}
|
||||
|
||||
float Game::getWaveLen (const char *fileName) {
|
||||
extern ConVar yb_chatter_path;
|
||||
const char *filePath = strings.format ("%s/%s/%s.wav", getModName (), yb_chatter_path.str (), fileName);
|
||||
auto filePath = strings.format ("%s/%s/%s.wav", getModName (), cv_chatter_path.str (), fileName);
|
||||
|
||||
File fp (filePath, "rb");
|
||||
|
||||
|
|
@ -250,7 +287,7 @@ float Game::getWaveLen (const char *fileName) {
|
|||
uint16 bitsPerSample;
|
||||
char dataChunkId[4];
|
||||
unsigned long dataChunkLength;
|
||||
} waveHdr;
|
||||
} waveHdr {};
|
||||
|
||||
plat.bzero (&waveHdr, sizeof (waveHdr));
|
||||
|
||||
|
|
@ -258,12 +295,12 @@ float Game::getWaveLen (const char *fileName) {
|
|||
logger.error ("Wave File %s - has wrong or unsupported format", filePath);
|
||||
return 0.0f;
|
||||
}
|
||||
fp.close ();
|
||||
|
||||
if (strncmp (waveHdr.chunkID, "WAVE", 4) != 0) {
|
||||
logger.error ("Wave File %s - has wrong wave chunk id", filePath);
|
||||
return 0.0f;
|
||||
}
|
||||
fp.close ();
|
||||
|
||||
if (waveHdr.dataChunkLength == 0) {
|
||||
logger.error ("Wave File %s - has zero length!", filePath);
|
||||
|
|
@ -329,7 +366,7 @@ void Game::registerEngineCommand (const char *command, void func ()) {
|
|||
|
||||
// check for hl pre 1.1.0.4, as it's doesn't have pfnAddServerCommand
|
||||
if (!plat.checkPointer (engfuncs.pfnAddServerCommand)) {
|
||||
logger.fatal ("YaPB's minimum HL engine version is 1.1.0.4 and minimum Counter-Strike is Beta 6.6. Please update your engine version.");
|
||||
logger.fatal ("%s's minimum HL engine version is 1.1.0.6 and minimum Counter-Strike is Beta 7.1. Please update your engine / game version.", product.name);
|
||||
}
|
||||
engfuncs.pfnAddServerCommand (const_cast <char *> (command), func);
|
||||
}
|
||||
|
|
@ -482,22 +519,26 @@ bool Game::isSoftwareRenderer () {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Game::addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, Var varType, bool missingAction, const char *regval, ConVar *self) {
|
||||
void Game::addNewCvar (const char *name, const char *value, const char *info, bool bounded, float min, float max, int32 varType, bool missingAction, const char *regval, ConVar *self) {
|
||||
// this function adds globally defined variable to registration stack
|
||||
|
||||
VarPair pair {};
|
||||
ConVarReg reg {};
|
||||
|
||||
pair.reg.name = const_cast <char *> (name);
|
||||
pair.reg.string = const_cast <char *> (value);
|
||||
pair.missing = missingAction;
|
||||
pair.regval = regval;
|
||||
pair.info = info;
|
||||
pair.bounded = bounded;
|
||||
reg.reg.name = const_cast <char *> (name);
|
||||
reg.reg.string = const_cast <char *> (value);
|
||||
reg.missing = missingAction;
|
||||
reg.init = value;
|
||||
reg.info = info;
|
||||
reg.bounded = bounded;
|
||||
|
||||
if (regval) {
|
||||
reg.regval = regval;
|
||||
}
|
||||
|
||||
if (bounded) {
|
||||
pair.min = min;
|
||||
pair.max = max;
|
||||
pair.initial = static_cast <float> (atof (value));
|
||||
reg.min = min;
|
||||
reg.max = max;
|
||||
reg.initial = static_cast <float> (atof (value));
|
||||
}
|
||||
|
||||
auto eflags = FCVAR_EXTDLL;
|
||||
|
|
@ -512,15 +553,24 @@ void Game::addNewCvar (const char *name, const char *value, const char *info, bo
|
|||
eflags |= FCVAR_PROTECTED;
|
||||
}
|
||||
|
||||
pair.reg.flags = eflags;
|
||||
pair.self = self;
|
||||
pair.type = varType;
|
||||
reg.reg.flags = eflags;
|
||||
reg.self = self;
|
||||
reg.type = varType;
|
||||
|
||||
m_cvars.push (cr::move (pair));
|
||||
m_cvars.push (cr::move (reg));
|
||||
}
|
||||
|
||||
void Game::checkCvarsBounds () {
|
||||
for (const auto &var : m_cvars) {
|
||||
|
||||
// read only cvar is not changeable
|
||||
if (var.type == Var::ReadOnly && !var.init.empty ()) {
|
||||
if (var.init != var.self->str ()) {
|
||||
var.self->set (var.init.chars ());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!var.bounded || !var.self) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -544,7 +594,7 @@ void Game::registerCvars (bool gameVars) {
|
|||
ConVar &self = *var.self;
|
||||
cvar_t ® = var.reg;
|
||||
|
||||
if (var.type != Var::NoRegister) {
|
||||
if (var.type != Var::GameRef) {
|
||||
self.ptr = engfuncs.pfnCVarGetPointer (reg.name);
|
||||
|
||||
if (!self.ptr) {
|
||||
|
|
@ -565,8 +615,8 @@ void Game::registerCvars (bool gameVars) {
|
|||
self.ptr = engfuncs.pfnCVarGetPointer (reg.name);
|
||||
|
||||
if (var.missing && !self.ptr) {
|
||||
if (reg.string == nullptr && var.regval != nullptr) {
|
||||
reg.string = const_cast <char *> (var.regval);
|
||||
if (reg.string == nullptr && !var.regval.empty ()) {
|
||||
reg.string = const_cast <char *> (var.regval.chars ());
|
||||
reg.flags |= FCVAR_SERVER;
|
||||
}
|
||||
engfuncs.pfnCVarRegister (&var.reg);
|
||||
|
|
@ -600,10 +650,10 @@ bool Game::loadCSBinary () {
|
|||
libs.push ("cs.dylib");
|
||||
}
|
||||
|
||||
auto libCheck = [&] (const String &mod, const String &dll) {
|
||||
auto libCheck = [&] (StringRef mod, StringRef dll) {
|
||||
// try to load gamedll
|
||||
if (!m_gameLib) {
|
||||
logger.fatal ("Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", dll.chars (), mod.chars ());
|
||||
logger.fatal ("Unable to load gamedll \"%s\". Exiting... (gamedir: %s)", dll, mod);
|
||||
}
|
||||
auto ent = m_gameLib.resolve <EntityFunction> ("trigger_random_unique");
|
||||
|
||||
|
|
@ -616,7 +666,7 @@ bool Game::loadCSBinary () {
|
|||
|
||||
// search the libraries inside game dlls directory
|
||||
for (const auto &lib : libs) {
|
||||
auto path = strings.format ("%s/dlls/%s", modname, lib.chars ());
|
||||
auto path = strings.format ("%s/dlls/%s", modname, lib);
|
||||
|
||||
// if we can't read file, skip it
|
||||
if (!File::exists (path)) {
|
||||
|
|
@ -678,30 +728,36 @@ bool Game::loadCSBinary () {
|
|||
|
||||
bool Game::postload () {
|
||||
|
||||
// register logger
|
||||
logger.initialize (strings.format ("%slogs/%s.log", graph.getDataDirectory (false), product.folder), [] (const char *msg) {
|
||||
game.print (msg);
|
||||
});
|
||||
|
||||
// ensure we're have all needed directories
|
||||
for (const auto &dir : StringArray { "conf/lang", "data/learned", "data/graph", "data/logs" }) {
|
||||
File::createPath (strings.format ("%s/addons/yapb/%s", getModName (), dir.chars ()));
|
||||
for (const auto &dir : StringArray { "conf/lang", "data/train", "data/graph", "data/logs" }) {
|
||||
File::createPath (strings.format ("%s/addons/%s/%s", getModName (), product.folder, dir));
|
||||
}
|
||||
|
||||
// set out user agent for http stuff
|
||||
http.setUserAgent (strings.format ("%s/%s", PRODUCT_SHORT_NAME, PRODUCT_VERSION));
|
||||
http.setUserAgent (strings.format ("%s/%s", product.name, product.version));
|
||||
|
||||
// register bot cvars
|
||||
game.registerCvars ();
|
||||
|
||||
// register server command(s)
|
||||
registerEngineCommand ("yapb", [] () {
|
||||
ctrl.handleEngineCommands ();
|
||||
});
|
||||
// handle prefixes
|
||||
static StringArray prefixes = { "yb", "yapb" };
|
||||
|
||||
registerEngineCommand ("yb", [] () {
|
||||
ctrl.handleEngineCommands ();
|
||||
// register all our handlers
|
||||
for (const auto &prefix : prefixes) {
|
||||
registerEngineCommand (prefix.chars (), [] () {
|
||||
ctrl.handleEngineCommands ();
|
||||
});
|
||||
}
|
||||
|
||||
// register fake metamod command handler if we not! under mm
|
||||
if (!(game.is (GameFlags::Metamod))) {
|
||||
game.registerEngineCommand ("meta", [] () {
|
||||
game.print ("You're launched standalone version of %s. Metamod is not installed or not enabled!", PRODUCT_SHORT_NAME);
|
||||
game.print ("You're launched standalone version of %s. Metamod is not installed or not enabled!", product.name);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -747,7 +803,7 @@ bool Game::postload () {
|
|||
if (is (GameFlags::Metamod)) {
|
||||
gameVersionFlags.push ("Metamod");
|
||||
}
|
||||
print ("%s v%s.0.%d successfully loaded for game: Counter-Strike %s (%s).\n", PRODUCT_SHORT_NAME, PRODUCT_VERSION, util.buildNumber (), gameVersionStr.chars (), String::join (gameVersionFlags, ", ").chars ());
|
||||
print ("\n%s v%s.%s successfully loaded for game: Counter-Strike %s.\n\tFlags: %s.\n", product.name, product.version, product.build.count, gameVersionStr, gameVersionFlags.empty () ? "None" : String::join (gameVersionFlags, ", "));
|
||||
};
|
||||
|
||||
if (plat.android) {
|
||||
|
|
@ -785,7 +841,7 @@ void Game::applyGameModes () {
|
|||
}
|
||||
|
||||
// handle cvar cases
|
||||
switch (yb_csdm_mode.int_ ()) {
|
||||
switch (cv_csdm_mode.int_ ()) {
|
||||
default:
|
||||
case 0:
|
||||
break;
|
||||
|
|
@ -843,6 +899,9 @@ void Game::slowFrame () {
|
|||
// check if we're need to autokill bots
|
||||
bots.maintainAutoKill ();
|
||||
|
||||
// maintain leaders selection upon round start
|
||||
bots.maintainLeaders ();
|
||||
|
||||
// update client pings
|
||||
util.calculatePings ();
|
||||
|
||||
|
|
@ -858,12 +917,15 @@ void Game::slowFrame () {
|
|||
// check the cvar bounds
|
||||
checkCvarsBounds ();
|
||||
|
||||
// refresh bomb origin in case some plugin moved it out
|
||||
graph.setBombOrigin ();
|
||||
|
||||
// display welcome message
|
||||
util.checkWelcome ();
|
||||
m_slowFrame = time () + 1.0f;
|
||||
}
|
||||
|
||||
void Game::searchEntities (const String &field, const String &value, EntitySearch functor) {
|
||||
void Game::searchEntities (StringRef field, StringRef value, EntitySearch functor) {
|
||||
edict_t *ent = nullptr;
|
||||
|
||||
while (!game.isNullEntity (ent = engfuncs.pfnFindEntityByString (ent, field.chars (), value.chars ()))) {
|
||||
|
|
@ -877,7 +939,7 @@ void Game::searchEntities (const String &field, const String &value, EntitySearc
|
|||
}
|
||||
}
|
||||
|
||||
void Game::searchEntities (const Vector &position, const float radius, EntitySearch functor) {
|
||||
void Game::searchEntities (const Vector &position, float radius, EntitySearch functor) {
|
||||
edict_t *ent = nullptr;
|
||||
const Vector &pos = position.empty () ? m_startEntity->v.origin : position;
|
||||
|
||||
|
|
@ -898,7 +960,7 @@ bool Game::isShootableBreakable (edict_t *ent) {
|
|||
}
|
||||
|
||||
if (strcmp (ent->v.classname.chars (), "func_breakable") == 0 || (strcmp (ent->v.classname.chars (), "func_pushable") == 0 && (ent->v.spawnflags & SF_PUSH_BREAKABLE))) {
|
||||
return ent->v.takedamage != DAMAGE_NO && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY) && ent->v.health < 500.0f;
|
||||
return !cr::fequal (ent->v.takedamage, DAMAGE_NO) && ent->v.impulse <= 0 && !(ent->v.flags & FL_WORLDBRUSH) && !(ent->v.spawnflags & SF_BREAK_TRIGGER_ONLY) && ent->v.health < 500.0f;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -927,7 +989,7 @@ void LightMeasure::animateLight () {
|
|||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
const int index = static_cast <int> (game.time () * 10.0f);
|
||||
|
||||
for (int j = 0; j < MAX_LIGHTSTYLES; ++j) {
|
||||
for (auto j = 0; j < MAX_LIGHTSTYLES; ++j) {
|
||||
if (!m_lightstyle[j].length) {
|
||||
m_lightstyleValue[j] = 256;
|
||||
continue;
|
||||
|
|
@ -948,15 +1010,15 @@ void LightMeasure::updateLight (int style, char *value) {
|
|||
|
||||
if (strings.isEmpty (value)){
|
||||
m_lightstyle[style].length = 0u;
|
||||
m_lightstyle[style].map[0] = '\0';
|
||||
m_lightstyle[style].map[0] = kNullChar;
|
||||
|
||||
return;
|
||||
}
|
||||
const auto copyLimit = sizeof (m_lightstyle[style].map) - sizeof ('\0');
|
||||
const auto copyLimit = sizeof (m_lightstyle[style].map) - sizeof (kNullChar);
|
||||
strings.copy (m_lightstyle[style].map, value, copyLimit);
|
||||
|
||||
m_lightstyle[style].map[copyLimit] = '\0';
|
||||
m_lightstyle[style].length = strlen (m_lightstyle[style].map);
|
||||
m_lightstyle[style].map[copyLimit] = kNullChar;
|
||||
m_lightstyle[style].length = static_cast <int> (strlen (m_lightstyle[style].map));
|
||||
}
|
||||
|
||||
template <typename S, typename M> bool LightMeasure::recursiveLightPoint (const M *node, const Vector &start, const Vector &end) {
|
||||
|
|
@ -1082,40 +1144,47 @@ float LightMeasure::getSkyColor () {
|
|||
return static_cast <float> (Color (sv_skycolor_r.int_ (), sv_skycolor_g.int_ (), sv_skycolor_b.int_ ()).avg ());
|
||||
}
|
||||
|
||||
DynamicEntityLink::Handle DynamicEntityLink::search (Handle module, Name function) {
|
||||
const auto lookup = [&] (Handle handle) {
|
||||
Handle ret = nullptr;
|
||||
|
||||
if (m_dlsym.disable ()) {
|
||||
ret = MODULE_SYMBOL (reinterpret_cast <MODULE_HANDLE> (handle), function);
|
||||
m_dlsym.enable ();
|
||||
}
|
||||
return ret;
|
||||
SharedLibrary::Handle EntityLinkage::lookup (SharedLibrary::Handle module, const char *function) {
|
||||
const auto resolve = [&] (SharedLibrary::Handle handle) {
|
||||
return reinterpret_cast <SharedLibrary::Handle> (m_dlsym.call <decltype (HOOK_FUNCTION)> (static_cast <HOOK_CAST> (handle), function));
|
||||
};
|
||||
|
||||
// skip any ordinals requests on windows
|
||||
if (plat.win32 && (static_cast <uint16> (reinterpret_cast <uint32> (function) >> 16) & 0xffff) == 0) {
|
||||
return resolve (module);
|
||||
}
|
||||
|
||||
static const auto &gamedll = game.lib ();
|
||||
static const auto &yapb = m_self;
|
||||
static const auto &self = m_self;
|
||||
|
||||
// if requested module is yapb, put in cache the looked up symbol
|
||||
if (yapb.handle () == module) {
|
||||
if (m_exports.exists (function)) {
|
||||
return m_exports[function];
|
||||
}
|
||||
auto address = lookup (yapb.handle ());
|
||||
// if requested module is yapb module, put in cache the looked up symbol
|
||||
if (self.handle () != module) {
|
||||
return resolve (module);
|
||||
}
|
||||
auto botAddr = resolve (self.handle ());
|
||||
|
||||
if (!address) {
|
||||
auto gameAddress = lookup (gamedll.handle ());
|
||||
if (!botAddr) {
|
||||
auto gameAddr = resolve (gamedll.handle ());
|
||||
|
||||
if (gameAddress) {
|
||||
m_exports[function] = gameAddress;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_exports[function] = address;
|
||||
}
|
||||
|
||||
if (m_exports.exists (function)) {
|
||||
return m_exports[function];
|
||||
if (gameAddr) {
|
||||
m_exports[function] = gameAddr;
|
||||
}
|
||||
}
|
||||
return lookup (module);
|
||||
else {
|
||||
m_exports[function] = botAddr;
|
||||
}
|
||||
|
||||
if (m_exports.exists (function)) {
|
||||
return m_exports[function];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EntityLinkage::initialize () {
|
||||
if (plat.arm) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_dlsym.patch (reinterpret_cast <SharedLibrary::Handle> (&HOOK_FUNCTION), reinterpret_cast <SharedLibrary::Handle> (&EntityLinkage::replacement));
|
||||
m_self.locate (&engfuncs);
|
||||
}
|
||||
|
|
@ -1,15 +1,22 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_graph_fixcamp ("yb_graph_fixcamp", "1", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
||||
ConVar yb_graph_url ("yb_graph_url", "http://graph.yapb.ru", "Specifies the URL from bots will be able to download graph in case of missing local one.", false);
|
||||
ConVar cv_graph_fixcamp ("ub_graph_fixcamp", "1", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
||||
ConVar cv_graph_url ("ub_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one.", false, 0.0f, 0.0f);
|
||||
|
||||
void BotGraph::initGraph () {
|
||||
// this function initialize the graph structures..
|
||||
|
|
@ -639,7 +646,7 @@ void BotGraph::add (int type, const Vector &pos) {
|
|||
}
|
||||
m_paths.push (Path {});
|
||||
|
||||
index = m_paths.length () - 1;
|
||||
index = length () - 1;
|
||||
path = &m_paths[index];
|
||||
|
||||
path->number = index;
|
||||
|
|
@ -1164,7 +1171,7 @@ void BotGraph::loadPractice () {
|
|||
}
|
||||
|
||||
bool dataLoaded = loadStorage <Practice> ("prc", "Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr, nullptr);
|
||||
int count = m_paths.length ();
|
||||
int count = length ();
|
||||
|
||||
// set's the highest damage if loaded ok
|
||||
if (dataLoaded) {
|
||||
|
|
@ -1351,20 +1358,31 @@ void BotGraph::initNarrowPlaces () {
|
|||
ang.angleVectors (&forward, &right, &upward);
|
||||
|
||||
// helper lambda
|
||||
auto directionCheck = [&] (const Vector &to, int weight) {
|
||||
auto directionCheck = [&] (const Vector &to) -> bool {
|
||||
game.testLine (path.origin + offset, to, TraceIgnore::None, nullptr, &tr);
|
||||
|
||||
// check if we're hit worldspawn entity
|
||||
if (tr.pHit == worldspawn && tr.flFraction < 1.0f) {
|
||||
accumWeight += weight;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
directionCheck (-forward * distance, 1);
|
||||
|
||||
directionCheck (right * distance, 1);
|
||||
directionCheck (-right * distance, 1);
|
||||
if (directionCheck (-forward * distance)) {
|
||||
accumWeight += 1;
|
||||
}
|
||||
|
||||
directionCheck (upward * distance, 1);
|
||||
if (directionCheck (right * distance)) {
|
||||
accumWeight += 1;
|
||||
}
|
||||
|
||||
if (directionCheck (-right * distance)) {
|
||||
accumWeight += 1;
|
||||
}
|
||||
|
||||
if (directionCheck (upward * distance)) {
|
||||
accumWeight += 1;
|
||||
}
|
||||
}
|
||||
path.flags &= ~NodeFlag::Narrow;
|
||||
|
||||
|
|
@ -1410,7 +1428,7 @@ void BotGraph::initNodesTypes () {
|
|||
bool BotGraph::convertOldFormat () {
|
||||
MemFile fp (getOldFormatGraphName (true));
|
||||
|
||||
PODGraphHeader header;
|
||||
PODGraphHeader header {};
|
||||
plat.bzero (&header, sizeof (header));
|
||||
|
||||
// save for faster access
|
||||
|
|
@ -1473,14 +1491,14 @@ bool BotGraph::convertOldFormat () {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename U> bool BotGraph::saveStorage (const String &ext, const String &name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) {
|
||||
bool isGraph = (ext == "graph");
|
||||
template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) {
|
||||
bool isGraph = !!(options & StorageOption::Graph);
|
||||
|
||||
String filename;
|
||||
filename.assignf ("%s.%s", game.getMapName (), ext.chars ());
|
||||
filename.assignf ("%s.%s", game.getMapName (), ext);
|
||||
|
||||
if (data.empty ()) {
|
||||
logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name.chars (), filename.chars ());
|
||||
logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name, filename);
|
||||
return false;
|
||||
}
|
||||
else if (isGraph) {
|
||||
|
|
@ -1491,30 +1509,30 @@ template <typename U> bool BotGraph::saveStorage (const String &ext, const Strin
|
|||
}
|
||||
|
||||
// open the file
|
||||
File file (strings.format ("%s%s/%s", getDataDirectory (false), isGraph ? "graph" : "learned", filename.chars ()), "wb");
|
||||
File file (strings.format ("%s%s/%s", getDataDirectory (false), isGraph ? "graph" : "train", filename), "wb");
|
||||
|
||||
// no open no fun
|
||||
if (!file) {
|
||||
logger.error ("Unable to open %s file for writing (filename: '%s').", name.chars (), filename.chars ());
|
||||
logger.error ("Unable to open %s file for writing (filename: '%s').", name, filename);
|
||||
file.close ();
|
||||
|
||||
return false;
|
||||
}
|
||||
ULZ lz;
|
||||
|
||||
size_t rawLength = data.length () * sizeof (U);
|
||||
int32 rawLength = data.template length <int32> () * sizeof (U);
|
||||
SmallArray <uint8> compressed (rawLength + sizeof (uint8) * ULZ::Excess);
|
||||
|
||||
// try to compress
|
||||
auto compressedLength = lz.compress (reinterpret_cast <uint8 *> (data.data ()), rawLength, reinterpret_cast <uint8 *> (compressed.data ()));
|
||||
|
||||
if (compressedLength > 0) {
|
||||
StorageHeader hdr;
|
||||
StorageHeader hdr {};
|
||||
|
||||
hdr.magic = kStorageMagic;
|
||||
hdr.version = version;
|
||||
hdr.options = options;
|
||||
hdr.length = m_paths.length ();
|
||||
hdr.length = length ();
|
||||
hdr.compressed = compressedLength;
|
||||
hdr.uncompressed = rawLength;
|
||||
|
||||
|
|
@ -1525,10 +1543,10 @@ template <typename U> bool BotGraph::saveStorage (const String &ext, const Strin
|
|||
if ((options & StorageOption::Exten) && exten != nullptr) {
|
||||
file.write (exten, sizeof (ExtenHeader));
|
||||
}
|
||||
game.print ("Successfully saved Bots %s data.", name.chars ());
|
||||
game.print ("Successfully saved Bots %s data.", name);
|
||||
}
|
||||
else {
|
||||
logger.error ("Unable to compress %s data (filename: '%s').", name.chars (), filename.chars ());
|
||||
logger.error ("Unable to compress %s data (filename: '%s').", name, filename);
|
||||
file.close ();
|
||||
|
||||
return false;
|
||||
|
|
@ -1537,13 +1555,13 @@ template <typename U> bool BotGraph::saveStorage (const String &ext, const Strin
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename U> bool BotGraph::loadStorage (const String &ext, const String &name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32 *outOptions) {
|
||||
template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32 *outOptions) {
|
||||
String filename;
|
||||
filename.assignf ("%s.%s", game.getMapName (), ext.chars ()).lowercase ();
|
||||
filename.assignf ("%s.%s", game.getMapName (), ext).lowercase ();
|
||||
|
||||
// graphs can be downloaded...
|
||||
bool isGraph = (ext == "graph");
|
||||
MemFile file (strings.format ("%s%s/%s", getDataDirectory (true), isGraph ? "graph" : "learned", filename.chars ())); // open the file
|
||||
bool isGraph = !!(options & StorageOption::Graph);
|
||||
MemFile file (strings.format ("%s%s/%s", getDataDirectory (true), isGraph ? "graph" : "train", filename)); // open the file
|
||||
|
||||
// resize data to fit the stuff
|
||||
auto resizeData = [&] (const size_t length) {
|
||||
|
|
@ -1559,48 +1577,24 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
resizeData (m_paths.length () * m_paths.length ());
|
||||
}
|
||||
|
||||
// error has occured
|
||||
auto bailout = [&] (const char *fmt, ...) -> bool {
|
||||
va_list args;
|
||||
auto result = strings.chars ();
|
||||
|
||||
// concatenate string
|
||||
va_start (args, fmt);
|
||||
vsnprintf (result, StringBuffer::StaticBufferSize, fmt, args);
|
||||
va_end (args);
|
||||
|
||||
logger.error (result);
|
||||
|
||||
// if graph reset paths
|
||||
if (isGraph) {
|
||||
bots.kickEveryone (true);
|
||||
|
||||
m_tempStrings = result;
|
||||
m_paths.clear ();
|
||||
}
|
||||
file.close ();
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// if graph & attempted to load multiple times, bail out, we're failed
|
||||
if (isGraph && ++m_loadAttempts > 2) {
|
||||
m_loadAttempts = 0;
|
||||
return bailout ("Unable to load %s (filename: '%s'). Download process has failed as well. No nodes has been found.", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Unable to load %s (filename: '%s'). Download process has failed as well. No nodes has been found.", name, filename);
|
||||
}
|
||||
|
||||
// downloader for graph
|
||||
auto download = [&] () -> bool {
|
||||
auto toDownload = strings.format ("%sgraph/%s", getDataDirectory (false), filename.chars ());
|
||||
auto fromDownload = strings.format ("%s/graph/%s", yb_graph_url.str (), filename.chars ());
|
||||
auto toDownload = strings.format ("%sgraph/%s", getDataDirectory (false), filename);
|
||||
auto fromDownload = strings.format ("%s/graph/%s", cv_graph_url.str (), filename);
|
||||
|
||||
// try to download
|
||||
if (http.downloadFile (fromDownload, toDownload)) {
|
||||
game.print ("%s file '%s' successfully downloaded. Processing...", name.chars (), filename.chars ());
|
||||
game.print ("%s file '%s' successfully downloaded. Processing...", name, filename);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
game.print ("Can't download '%s'. from '%s' to '%s'... (%d).", filename.chars (), fromDownload, toDownload, http.getLastStatusCode ());
|
||||
game.print ("Can't download '%s'. from '%s' to '%s'... (%d).", filename, fromDownload, toDownload, http.getLastStatusCode ());
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
@ -1628,11 +1622,11 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
if (tryReload ()) {
|
||||
return true;
|
||||
}
|
||||
return bailout ("Unable to open %s file for reading (filename: '%s').", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Unable to open %s file for reading (filename: '%s').", name, filename);
|
||||
}
|
||||
|
||||
// read the header
|
||||
StorageHeader hdr;
|
||||
StorageHeader hdr {};
|
||||
file.read (&hdr, sizeof (StorageHeader));
|
||||
|
||||
// check the magic
|
||||
|
|
@ -1640,12 +1634,12 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
if (tryReload ()) {
|
||||
return true;
|
||||
}
|
||||
return bailout ("Unable to read magic of %s (filename: '%s').", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Unable to read magic of %s (filename: '%s').", name, filename);
|
||||
}
|
||||
|
||||
// check the path-numbers
|
||||
if (!isGraph && hdr.length != length ()) {
|
||||
return bailout ("Damaged %s (filename: '%s'). Mismatch number of nodes (got: '%d', need: '%d').", name.chars (), filename.chars (), hdr.length, m_paths.length ());
|
||||
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Mismatch number of nodes (got: '%d', need: '%d').", name, filename, hdr.length, m_paths.length ());
|
||||
}
|
||||
|
||||
// check the count
|
||||
|
|
@ -1653,7 +1647,7 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
if (tryReload ()) {
|
||||
return true;
|
||||
}
|
||||
return bailout ("Damaged %s (filename: '%s'). Paths length is overflowed (got: '%d').", name.chars (), filename.chars (), hdr.length);
|
||||
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Paths length is overflowed (got: '%d').", name, filename, hdr.length);
|
||||
}
|
||||
|
||||
// check the version
|
||||
|
|
@ -1661,12 +1655,12 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
if (tryReload ()) {
|
||||
return true;
|
||||
}
|
||||
return bailout ("Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name.chars (), filename.chars (), hdr.version, version);
|
||||
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version);
|
||||
}
|
||||
|
||||
// check the storage type
|
||||
if ((hdr.options & options) != options) {
|
||||
return bailout ("Incorrect storage format for %s (filename: '%s').", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Incorrect storage format for %s (filename: '%s').", name, filename);
|
||||
}
|
||||
SmallArray <uint8> compressed (hdr.compressed + sizeof (uint8) * ULZ::Excess);
|
||||
|
||||
|
|
@ -1681,7 +1675,7 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
|
||||
// try to uncompress
|
||||
if (lz.uncompress (compressed.data (), hdr.compressed, reinterpret_cast <uint8 *> (data.data ()), hdr.uncompressed) == ULZ::UncompressFailure) {
|
||||
return bailout ("Unable to decompress ULZ data for %s (filename: '%s').", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Unable to decompress ULZ data for %s (filename: '%s').", name, filename);
|
||||
}
|
||||
else {
|
||||
|
||||
|
|
@ -1693,16 +1687,15 @@ template <typename U> bool BotGraph::loadStorage (const String &ext, const Strin
|
|||
if ((hdr.options & StorageOption::Exten) && exten != nullptr) {
|
||||
file.read (exten, sizeof (ExtenHeader));
|
||||
}
|
||||
game.print ("Successfully loaded Bots %s data (%d/%.2fMB).", name.chars (), data.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f);
|
||||
game.print ("Successfully loaded Bots %s data (%d/%.2fMB).", name, m_paths.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f);
|
||||
file.close ();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return bailout ("Unable to read ULZ data for %s (filename: '%s').", name.chars (), filename.chars ());
|
||||
return raiseLoadingError (isGraph, file, "Unable to read ULZ data for %s (filename: '%s').", name, filename);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BotGraph::loadGraphData () {
|
||||
|
|
@ -1727,7 +1720,7 @@ bool BotGraph::loadGraphData () {
|
|||
m_tempStrings.assign ("Using Official Navigation Graph");
|
||||
}
|
||||
else {
|
||||
m_tempStrings.assignf ("Navigation Graph Authord By: %s", exten.author);
|
||||
m_tempStrings.assignf ("Navigation Graph Authored By: %s", exten.author);
|
||||
}
|
||||
initNodesTypes ();
|
||||
loadPathMatrix ();
|
||||
|
|
@ -1741,8 +1734,8 @@ bool BotGraph::loadGraphData () {
|
|||
game.print ("Warning: Graph data is probably not for this map. Please check bots behaviour.");
|
||||
}
|
||||
}
|
||||
extern ConVar yb_debug_goal;
|
||||
yb_debug_goal.set (kInvalidNodeIndex);
|
||||
extern ConVar cv_debug_goal;
|
||||
cv_debug_goal.set (kInvalidNodeIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1786,7 +1779,7 @@ void BotGraph::saveOldFormat () {
|
|||
|
||||
header.mapName[31] = 0;
|
||||
header.fileVersion = StorageVersion::Podbot;
|
||||
header.pointNumber = m_paths.length ();
|
||||
header.pointNumber = length ();
|
||||
|
||||
File fp;
|
||||
|
||||
|
|
@ -1846,7 +1839,7 @@ bool BotGraph::isNodeReacheable (const Vector &src, const Vector &destination) {
|
|||
game.testLine (src, destination, TraceIgnore::Monsters, m_editor, &tr);
|
||||
|
||||
// if node is visible from current position (even behind head)...
|
||||
if (tr.flFraction >= 1.0f || (tr.pHit && strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0)) {
|
||||
if (tr.pHit && (tr.flFraction >= 1.0f || strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0)) {
|
||||
// if it's a door check if nothing blocks behind
|
||||
if (strncmp ("func_door", tr.pHit->v.classname.chars (), 9) == 0) {
|
||||
game.testLine (tr.vecEndPos, destination, TraceIgnore::Monsters, tr.pHit, &tr);
|
||||
|
|
@ -2125,40 +2118,40 @@ void BotGraph::frame () {
|
|||
float nodeHalfHeight = nodeHeight * 0.5f;
|
||||
|
||||
// all nodes are by default are green
|
||||
Color nodeColor = Color (-1, -1, -1);
|
||||
Color nodeColor { -1, -1, -1 };
|
||||
|
||||
// colorize all other nodes
|
||||
if (path.flags & NodeFlag::Camp) {
|
||||
nodeColor = Color (0, 255, 255);
|
||||
nodeColor = { 0, 255, 255 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::Goal) {
|
||||
nodeColor = Color (128, 0, 255);
|
||||
nodeColor = { 128, 0, 255 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::Ladder) {
|
||||
nodeColor = Color (128, 64, 0);
|
||||
nodeColor = { 128, 64, 0 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::Rescue) {
|
||||
nodeColor = Color (255, 255, 255);
|
||||
nodeColor = { 255, 255, 255 };
|
||||
}
|
||||
else {
|
||||
nodeColor = Color (0, 255, 0);
|
||||
nodeColor = { 0, 255, 0 };
|
||||
}
|
||||
|
||||
// colorize additional flags
|
||||
Color nodeFlagColor = Color (-1, -1, -1);
|
||||
Color nodeFlagColor { -1, -1, -1 };
|
||||
|
||||
// check the colors
|
||||
if (path.flags & NodeFlag::Sniper) {
|
||||
nodeFlagColor = Color (130, 87, 0);
|
||||
nodeFlagColor = { 130, 87, 0 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::NoHostage) {
|
||||
nodeFlagColor = Color (255, 255, 255);
|
||||
nodeFlagColor = { 255, 255, 255 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::TerroristOnly) {
|
||||
nodeFlagColor = Color (255, 0, 0);
|
||||
nodeFlagColor = { 255, 0, 0 };
|
||||
}
|
||||
else if (path.flags & NodeFlag::CTOnly) {
|
||||
nodeFlagColor = Color (0, 0, 255);
|
||||
nodeFlagColor = { 0, 0, 255 };
|
||||
}
|
||||
int nodeWidth = 14;
|
||||
|
||||
|
|
@ -2192,17 +2185,17 @@ void BotGraph::frame () {
|
|||
|
||||
// finding node - pink arrow
|
||||
if (m_findWPIndex != kInvalidNodeIndex) {
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_findWPIndex].origin, 10, 0, Color (128, 0, 128), 200, 0, 5, DrawLine::Arrow);
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_findWPIndex].origin, 10, 0, { 128, 0, 128 }, 200, 0, 5, DrawLine::Arrow);
|
||||
}
|
||||
|
||||
// cached node - yellow arrow
|
||||
if (m_cacheNodeIndex != kInvalidNodeIndex) {
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_cacheNodeIndex].origin, 10, 0, Color (255, 255, 0), 200, 0, 5, DrawLine::Arrow);
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_cacheNodeIndex].origin, 10, 0, { 255, 255, 0 }, 200, 0, 5, DrawLine::Arrow);
|
||||
}
|
||||
|
||||
// node user facing at - white arrow
|
||||
if (m_facingAtIndex != kInvalidNodeIndex) {
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_facingAtIndex].origin, 10, 0, Color (255, 255, 255), 200, 0, 5, DrawLine::Arrow);
|
||||
game.drawLine (m_editor, m_editor->v.origin, m_paths[m_facingAtIndex].origin, 10, 0, { 255, 255, 255 }, 200, 0, 5, DrawLine::Arrow);
|
||||
}
|
||||
m_arrowDisplayTime = game.time ();
|
||||
}
|
||||
|
|
@ -2228,8 +2221,8 @@ void BotGraph::frame () {
|
|||
const auto &end = path.origin + Vector (path.end.x, path.end.y, 0.0f).forward () * 500.0f; // camp end
|
||||
|
||||
// draw it now
|
||||
game.drawLine (m_editor, source, start, 10, 0, Color (255, 0, 0), 200, 0, 10);
|
||||
game.drawLine (m_editor, source, end, 10, 0, Color (255, 0, 0), 200, 0, 10);
|
||||
game.drawLine (m_editor, source, start, 10, 0, { 255, 0, 0 }, 200, 0, 10);
|
||||
game.drawLine (m_editor, source, end, 10, 0, { 255, 0, 0 }, 200, 0, 10);
|
||||
}
|
||||
|
||||
// draw the connections
|
||||
|
|
@ -2239,30 +2232,30 @@ void BotGraph::frame () {
|
|||
}
|
||||
// jump connection
|
||||
if (link.flags & PathFlag::Jump) {
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, Color (255, 0, 128), 200, 0, 10);
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, { 255, 0, 128 }, 200, 0, 10);
|
||||
}
|
||||
else if (isConnected (link.index, nearestIndex)) { // twoway connection
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, Color (255, 255, 0), 200, 0, 10);
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, { 255, 255, 0 }, 200, 0, 10);
|
||||
}
|
||||
else { // oneway connection
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, Color (250, 250, 250), 200, 0, 10);
|
||||
game.drawLine (m_editor, path.origin, m_paths[link.index].origin, 5, 0, { 50, 250, 25 }, 200, 0, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// now look for oneway incoming connections
|
||||
for (const auto &connected : m_paths) {
|
||||
if (isConnected (connected.number, path.number) && !isConnected (path.number, connected.number)) {
|
||||
game.drawLine (m_editor, path.origin, connected.origin, 5, 0, Color (0, 192, 96), 200, 0, 10);
|
||||
game.drawLine (m_editor, path.origin, connected.origin, 5, 0, { 0, 192, 96 }, 200, 0, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// draw the radius circle
|
||||
Vector origin = (path.flags & NodeFlag::Crouch) ? path.origin : path.origin - Vector (0.0f, 0.0f, 18.0f);
|
||||
Color radiusColor (0, 0, 255);
|
||||
Color radiusColor { 0, 0, 255 };
|
||||
|
||||
// if radius is nonzero, draw a full circle
|
||||
if (path.radius > 0.0f) {
|
||||
float sqr = cr::sqrtf (path.radius * path.radius * 0.5f);
|
||||
float sqr = cr::sqrtf (cr::square (path.radius) * 0.5f);
|
||||
|
||||
game.drawLine (m_editor, origin + Vector (path.radius, 0.0f, 0.0f), origin + Vector (sqr, -sqr, 0.0f), 5, 0, radiusColor, 200, 0, 10);
|
||||
game.drawLine (m_editor, origin + Vector (sqr, -sqr, 0.0f), origin + Vector (0.0f, -path.radius, 0.0f), 5, 0, radiusColor, 200, 0, 10);
|
||||
|
|
@ -2288,11 +2281,11 @@ void BotGraph::frame () {
|
|||
int dangerIndex = getDangerIndex (game.getTeam (m_editor), nearestIndex, nearestIndex);
|
||||
|
||||
if (exists (dangerIndex)) {
|
||||
game.drawLine (m_editor, path.origin, m_paths[dangerIndex].origin, 15, 0, Color (255, 0, 0), 200, 0, 10, DrawLine::Arrow); // draw a red arrow to this index's danger point
|
||||
game.drawLine (m_editor, path.origin, m_paths[dangerIndex].origin, 15, 0, { 255, 0, 0 }, 200, 0, 10, DrawLine::Arrow); // draw a red arrow to this index's danger point
|
||||
}
|
||||
}
|
||||
|
||||
auto getFlagsAsStr = [&] (int index) {
|
||||
auto getFlagsAsStr = [&] (int index) -> StringRef {
|
||||
const auto &path = m_paths[index];
|
||||
bool jumpPoint = false;
|
||||
|
||||
|
|
@ -2306,19 +2299,22 @@ void BotGraph::frame () {
|
|||
}
|
||||
|
||||
static String buffer;
|
||||
buffer.assignf ("%s%s%s%s%s%s%s%s%s%s%s%s%s", (path.flags == 0 && !jumpPoint) ? " (none)" : "", (path.flags & NodeFlag::Lift) ? " LIFT" : "", (path.flags & NodeFlag::Crouch) ? " CROUCH" : "", (path.flags & NodeFlag::Camp) ? " CAMP" : "", (path.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "", (path.flags & NodeFlag::CTOnly) ? " CT" : "", (path.flags & NodeFlag::Sniper) ? " SNIPER" : "", (path.flags & NodeFlag::Goal) ? " GOAL" : "", (path.flags & NodeFlag::Ladder) ? " LADDER" : "", (path.flags & NodeFlag::Rescue) ? " RESCUE" : "", (path.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "", (path.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : "");
|
||||
buffer.assignf ("%s%s%s%s%s%s%s%s%s%s%s%s", (path.flags & NodeFlag::Lift) ? " LIFT" : "", (path.flags & NodeFlag::Crouch) ? " CROUCH" : "", (path.flags & NodeFlag::Camp) ? " CAMP" : "", (path.flags & NodeFlag::TerroristOnly) ? " TERRORIST" : "", (path.flags & NodeFlag::CTOnly) ? " CT" : "", (path.flags & NodeFlag::Sniper) ? " SNIPER" : "", (path.flags & NodeFlag::Goal) ? " GOAL" : "", (path.flags & NodeFlag::Ladder) ? " LADDER" : "", (path.flags & NodeFlag::Rescue) ? " RESCUE" : "", (path.flags & NodeFlag::DoubleJump) ? " JUMPHELP" : "", (path.flags & NodeFlag::NoHostage) ? " NOHOSTAGE" : "", jumpPoint ? " JUMP" : "");
|
||||
|
||||
if (buffer.empty ()) {
|
||||
buffer.assign ("(none)");
|
||||
}
|
||||
// return the message buffer
|
||||
return buffer.chars ();
|
||||
return buffer;
|
||||
};
|
||||
|
||||
auto pathOriginStr = [&] (int index) {
|
||||
auto pathOriginStr = [&] (int index) -> StringRef {
|
||||
const auto &path = m_paths[index];
|
||||
|
||||
static String buffer;
|
||||
buffer.assignf ("(%.1f, %.1f, %.1f)", path.origin.x, path.origin.y, path.origin.z);
|
||||
|
||||
return buffer.chars ();
|
||||
return buffer;
|
||||
};
|
||||
|
||||
// display some information
|
||||
|
|
@ -2692,18 +2688,18 @@ void BotGraph::eraseFromDisk () {
|
|||
|
||||
// if we're delete graph, delete all corresponding to it files
|
||||
forErase.push (strings.format ("%s%s.pwf", data, map)); // graph itself
|
||||
forErase.push (strings.format ("%slearned/%s.exp", data, map)); // corresponding to practice
|
||||
forErase.push (strings.format ("%slearned/%s.vis", data, map)); // corresponding to vistable
|
||||
forErase.push (strings.format ("%slearned/%s.pmx", data, map)); // corresponding to matrix
|
||||
forErase.push (strings.format ("%strain/%s.exp", data, map)); // corresponding to practice
|
||||
forErase.push (strings.format ("%strain/%s.vis", data, map)); // corresponding to vistable
|
||||
forErase.push (strings.format ("%strain/%s.pmx", data, map)); // corresponding to matrix
|
||||
forErase.push (strings.format ("%sgraph/%s.graph", data, map)); // new format graph
|
||||
|
||||
for (const auto &item : forErase) {
|
||||
if (File::exists (item)) {
|
||||
plat.removeFile (item.chars ());
|
||||
game.print ("File %s, has been deleted from the hard disk", item.chars ());
|
||||
game.print ("File %s, has been deleted from the hard disk", item);
|
||||
}
|
||||
else {
|
||||
logger.error ("Unable to open %s", item.chars ());
|
||||
logger.error ("Unable to open %s", item);
|
||||
}
|
||||
}
|
||||
initGraph (); // reintialize points
|
||||
|
|
@ -2715,10 +2711,10 @@ const char *BotGraph::getDataDirectory (bool isMemoryFile) {
|
|||
buffer.clear ();
|
||||
|
||||
if (isMemoryFile) {
|
||||
buffer.assign ("addons/yapb/data/");
|
||||
buffer.assignf ("addons/%s/data/", product.folder);
|
||||
}
|
||||
else {
|
||||
buffer.assignf ("%s/addons/yapb/data/", game.getModName ());
|
||||
buffer.assignf ("%s/addons/%s/data/", game.getModName (), product.folder);
|
||||
}
|
||||
return buffer.chars ();
|
||||
}
|
||||
|
|
@ -2726,6 +2722,10 @@ const char *BotGraph::getDataDirectory (bool isMemoryFile) {
|
|||
void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
|
||||
// this function stores the bomb position as a vector
|
||||
|
||||
if (!game.mapIs (MapFlags::Demolition) || !bots.isBombPlanted ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
m_bombOrigin = nullptr;
|
||||
bots.setBombPlanted (false);
|
||||
|
|
@ -2737,14 +2737,22 @@ void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
|
|||
m_bombOrigin = pos;
|
||||
return;
|
||||
}
|
||||
bool wasFound = false;
|
||||
|
||||
game.searchEntities ("classname", "grenade", [&] (edict_t *ent) {
|
||||
if (strcmp (ent->v.model.chars (9), "c4.mdl") == 0) {
|
||||
m_bombOrigin = game.getEntityWorldOrigin (ent);
|
||||
wasFound = true;
|
||||
|
||||
return EntitySearchResult::Break;
|
||||
}
|
||||
return EntitySearchResult::Continue;
|
||||
});
|
||||
|
||||
if (!wasFound) {
|
||||
m_bombOrigin = nullptr;
|
||||
bots.setBombPlanted (false);
|
||||
}
|
||||
}
|
||||
|
||||
void BotGraph::startLearnJump () {
|
||||
|
|
@ -2877,7 +2885,7 @@ void BotGraph::updateGlobalPractice () {
|
|||
(practice + (i * length ()) + i)->index[team] = static_cast <int16> (bestIndex);
|
||||
}
|
||||
}
|
||||
constexpr int HALF_DAMAGE_VALUE = static_cast <int> (kMaxPracticeDamageValue * 0.5);
|
||||
constexpr auto kHalfDamageVal = static_cast <int> (kMaxPracticeDamageValue * 0.5);
|
||||
|
||||
// adjust values if overflow is about to happen
|
||||
if (adjustValues) {
|
||||
|
|
@ -2887,14 +2895,14 @@ void BotGraph::updateGlobalPractice () {
|
|||
if (i == j) {
|
||||
continue;
|
||||
}
|
||||
(practice + (i * length ()) + j)->damage[team] = static_cast <int16> (cr::clamp (getDangerDamage (team, i, j) - HALF_DAMAGE_VALUE, 0, kMaxPracticeDamageValue));
|
||||
(practice + (i * length ()) + j)->damage[team] = static_cast <int16> (cr::clamp (getDangerDamage (team, i, j) - kHalfDamageVal, 0, kMaxPracticeDamageValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int team = Team::Terrorist; team < kGameTeamNum; ++team) {
|
||||
m_highestDamage[team] = cr::clamp (m_highestDamage [team] - HALF_DAMAGE_VALUE, 1, kMaxPracticeDamageValue);
|
||||
m_highestDamage[team] = cr::clamp (m_highestDamage [team] - kHalfDamageVal, 1, kMaxPracticeDamageValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2919,7 +2927,7 @@ void BotGraph::convertFromPOD (Path &path, const PODPath &pod) {
|
|||
path.start = Vector (pod.csx, pod.csy, 0.0f);
|
||||
path.end = Vector (pod.cex, pod.cey, 0.0f);
|
||||
|
||||
if (yb_graph_fixcamp.bool_ ()) {
|
||||
if (cv_graph_fixcamp.bool_ ()) {
|
||||
convertCampDirection (path);
|
||||
}
|
||||
path.radius = pod.radius;
|
||||
|
|
@ -1,14 +1,21 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_version ("yb_version", PRODUCT_VERSION, Var::ReadOnly);
|
||||
ConVar cv_version ("ub_version", strings.format ("%s.%s", product.version, product.build.count), Var::ReadOnly);
|
||||
|
||||
gamefuncs_t dllapi;
|
||||
enginefuncs_t engfuncs;
|
||||
|
|
@ -22,12 +29,12 @@ globalvars_t *globals = nullptr;
|
|||
// metamod plugin information
|
||||
plugin_info_t Plugin_info = {
|
||||
META_INTERFACE_VERSION, // interface version
|
||||
PRODUCT_SHORT_NAME, // plugin name
|
||||
PRODUCT_VERSION, // plugin version
|
||||
PRODUCT_DATE, // date of creation
|
||||
PRODUCT_AUTHOR, // plugin author
|
||||
PRODUCT_URL, // plugin URL
|
||||
PRODUCT_LOGTAG, // plugin logtag
|
||||
product.name.chars (), // plugin name
|
||||
product.version.chars (), // plugin version
|
||||
product.date.chars (), // date of creation
|
||||
product.author.chars (), // plugin author
|
||||
product.url.chars (), // plugin URL
|
||||
product.logtag.chars (), // plugin logtag
|
||||
PT_CHANGELEVEL, // when loadable
|
||||
PT_ANYTIME, // when unloadable
|
||||
};
|
||||
|
|
@ -75,7 +82,7 @@ namespace variadic {
|
|||
}
|
||||
}
|
||||
|
||||
CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
||||
CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int) {
|
||||
// this function is called right after GiveFnptrsToDll() by the engine in the game DLL (or
|
||||
// what it BELIEVES to be the game DLL), in order to copy the list of MOD functions that can
|
||||
// be called by the engine, into a memory block pointed to by the functionTable pointer
|
||||
|
|
@ -89,11 +96,11 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
plat.bzero (table, sizeof (gamefuncs_t));
|
||||
|
||||
if (!(game.is (GameFlags::Metamod))) {
|
||||
auto api_GetEntityAPI = game.lib ().resolve <int (*) (gamefuncs_t *, int)> ("GetEntityAPI");
|
||||
auto api_GetEntityAPI = game.lib ().resolve <decltype (&GetEntityAPI)> (__FUNCTION__);
|
||||
|
||||
// pass other DLLs engine callbacks to function table...
|
||||
if (!api_GetEntityAPI || api_GetEntityAPI (&dllapi, INTERFACE_VERSION) == 0) {
|
||||
logger.fatal ("Could not resolve symbol \"%s\" in the game dll.", "GetEntityAPI");
|
||||
logger.fatal ("Could not resolve symbol \"%s\" in the game dll.", __FUNCTION__);
|
||||
}
|
||||
dllfuncs.dllapi_table = &dllapi;
|
||||
gpGamedllFuncs = &dllfuncs;
|
||||
|
|
@ -110,14 +117,6 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
// server is enabled. Here is a good place to do our own game session initialization, and
|
||||
// to register by the engine side the server commands we need to administrate our bots.
|
||||
|
||||
// register logger
|
||||
logger.initialize (strings.format ("%slogs/yapb.log", graph.getDataDirectory (false)), [] (const char *msg) {
|
||||
game.print (msg);
|
||||
});
|
||||
|
||||
// set correct version string
|
||||
yb_version.set (strings.format ("%d.%d.%d", PRODUCT_VERSION_DWORD_INTERNAL, util.buildNumber ()));
|
||||
|
||||
// execute main config
|
||||
conf.loadMainConfig ();
|
||||
conf.adjustWeaponPrices ();
|
||||
|
|
@ -134,8 +133,6 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
// Spawn() function is one of the functions any entity is supposed to have in the game DLL,
|
||||
// and any MOD is supposed to implement one for each of its entities.
|
||||
|
||||
game.precache ();
|
||||
|
||||
if (game.is (GameFlags::Metamod)) {
|
||||
RETURN_META_VALUE (MRES_IGNORED, 0);
|
||||
}
|
||||
|
|
@ -312,8 +309,8 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
// execute main config
|
||||
conf.loadMainConfig ();
|
||||
|
||||
if (File::exists (strings.format ("%s/maps/%s_yapb.cfg", game.getModName (), game.getMapName ()))) {
|
||||
game.serverCommand ("exec maps/%s_yapb.cfg", game.getMapName ());
|
||||
if (File::exists (strings.format ("%s/maps/%s_%s.cfg", game.getModName (), game.getMapName (), product.folder))) {
|
||||
game.serverCommand ("exec maps/%s_%s.cfg", game.getMapName (), product.folder);
|
||||
game.print ("Executing Map-Specific config file");
|
||||
}
|
||||
bots.initQuota ();
|
||||
|
|
@ -414,7 +411,7 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
|
||||
// if we're handle pings for bots and clients, clear IN_SCORE button so SV_ShouldUpdatePing engine function return false
|
||||
// and SV_EmitPings will not overwrite our results
|
||||
if (game.is (GameFlags::HasFakePings) && yb_show_latency.int_ () == 2) {
|
||||
if (game.is (GameFlags::HasFakePings) && cv_show_latency.int_ () == 2) {
|
||||
if ((cmd->buttons & IN_SCORE) || (ent->v.oldbuttons & IN_SCORE)) {
|
||||
cmd->buttons &= ~IN_SCORE;
|
||||
|
||||
|
|
@ -442,10 +439,10 @@ CR_EXPORT int GetEntityAPI2 (gamefuncs_t *table, int *) {
|
|||
}
|
||||
dllapi.pfnPM_Move (playerMove, server);
|
||||
};
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
|
||||
CR_LINKAGE_C int GetEntityAPI_Post (gamefuncs_t *table, int) {
|
||||
// this function is called right after GiveFnptrsToDll() by the engine in the game DLL (or
|
||||
// what it BELIEVES to be the game DLL), in order to copy the list of MOD functions that can
|
||||
// be called by the engine, into a memory block pointed to by the functionTable pointer
|
||||
|
|
@ -499,7 +496,7 @@ CR_LINKAGE_C int GetEntityAPI2_Post (gamefuncs_t *table, int *) {
|
|||
RETURN_META (MRES_IGNORED);
|
||||
};
|
||||
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
||||
|
|
@ -788,7 +785,7 @@ CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
|||
|
||||
table->pfnClientCommand = variadic::clientCommand;
|
||||
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion) {
|
||||
|
|
@ -798,15 +795,15 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
|
|||
// pass them too, else the DLL interfacing wouldn't be complete and the game possibly wouldn't
|
||||
// run properly.
|
||||
|
||||
auto api_GetNewDLLFunctions = game.lib ().resolve <int (*) (newgamefuncs_t *, int *)> (__FUNCTION__);
|
||||
auto api_GetNewDLLFunctions = game.lib ().resolve <decltype (&GetNewDLLFunctions)> (__FUNCTION__);
|
||||
|
||||
if (!api_GetNewDLLFunctions || !api_GetNewDLLFunctions (table, interfaceVersion)) {
|
||||
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
||||
return false;
|
||||
return HLFalse;
|
||||
}
|
||||
|
||||
dllfuncs.newapi_table = table;
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
|
||||
|
|
@ -835,7 +832,7 @@ CR_LINKAGE_C int GetEngineFunctions_Post (enginefuncs_t *table, int *) {
|
|||
RETURN_META_VALUE (MRES_IGNORED, 0);
|
||||
};
|
||||
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_EXPORT int Meta_Query (char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs) {
|
||||
|
|
@ -846,7 +843,7 @@ CR_EXPORT int Meta_Query (char *, plugin_info_t **pPlugInfo, mutil_funcs_t *pMet
|
|||
gpMetaUtilFuncs = pMetaUtilFuncs;
|
||||
*pPlugInfo = &Plugin_info;
|
||||
|
||||
return true; // tell metamod this plugin looks safe
|
||||
return HLTrue; // tell metamod this plugin looks safe
|
||||
}
|
||||
|
||||
CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs) {
|
||||
|
|
@ -856,10 +853,10 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
|||
|
||||
// metamod engine & dllapi function tables
|
||||
static metamod_funcs_t metamodFunctionTable = {
|
||||
nullptr, // pfnGetEntityAPI ()
|
||||
nullptr, // pfnGetEntityAPI_Post ()
|
||||
GetEntityAPI2, // pfnGetEntityAPI2 ()
|
||||
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post ()
|
||||
GetEntityAPI, // pfnGetEntityAPI ()
|
||||
GetEntityAPI_Post, // pfnGetEntityAPI_Post ()
|
||||
nullptr, // pfnGetEntityAPI2 ()
|
||||
nullptr, // pfnGetEntityAPI2_Post ()
|
||||
nullptr, // pfnGetNewDLLFunctions ()
|
||||
nullptr, // pfnGetNewDLLFunctions_Post ()
|
||||
GetEngineFunctions, // pfnGetEngineFunctions ()
|
||||
|
|
@ -868,7 +865,7 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
|||
|
||||
if (now > Plugin_info.loadable) {
|
||||
logger.error ("%s: plugin NOT attaching (can't load plugin right now)", Plugin_info.name);
|
||||
return false; // returning FALSE prevents metamod from attaching this plugin
|
||||
return HLFalse; // returning FALSE prevents metamod from attaching this plugin
|
||||
}
|
||||
|
||||
// keep track of the pointers to engine function tables metamod gives us
|
||||
|
|
@ -876,7 +873,7 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
|||
memcpy (functionTable, &metamodFunctionTable, sizeof (metamod_funcs_t));
|
||||
gpGamedllFuncs = pGamedllFuncs;
|
||||
|
||||
return true; // returning true enables metamod to attach this plugin
|
||||
return HLTrue; // returning true enables metamod to attach this plugin
|
||||
}
|
||||
|
||||
CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
||||
|
|
@ -885,7 +882,7 @@ CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
|||
|
||||
if (now > Plugin_info.unloadable && reason != PNL_CMD_FORCED) {
|
||||
logger.error ("%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name);
|
||||
return false; // returning FALSE prevents metamod from unloading this plugin
|
||||
return HLFalse; // returning FALSE prevents metamod from unloading this plugin
|
||||
}
|
||||
bots.kickEveryone (true); // kick all bots off this server
|
||||
|
||||
|
|
@ -896,7 +893,7 @@ CR_EXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
|
|||
// make sure all stuff cleared
|
||||
bots.destroy ();
|
||||
|
||||
return true;
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
CR_EXPORT void Meta_Init () {
|
||||
|
|
@ -908,7 +905,7 @@ CR_EXPORT void Meta_Init () {
|
|||
|
||||
// games GiveFnptrsToDll is a bit tricky
|
||||
#if defined(CR_WINDOWS)
|
||||
# if defined(CR_CXX_MSVC) || defined (CR_CXX_MSVC)
|
||||
# if defined(CR_CXX_MSVC) || defined (CR_CXX_CLANG)
|
||||
# if defined (CR_ARCH_X86)
|
||||
# pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1")
|
||||
# endif
|
||||
|
|
@ -916,14 +913,14 @@ CR_EXPORT void Meta_Init () {
|
|||
# endif
|
||||
# if defined(CR_CXX_MSVC) && !defined(CR_ARCH_X64)
|
||||
# define DLL_GIVEFNPTRSTODLL CR_LINKAGE_C void CR_STDCALL
|
||||
# elif defined(CR_CXX_CLANG) || defined(CR_ARCH_X64)
|
||||
# elif defined(CR_CXX_CLANG) || defined(CR_CXX_GCC) || defined(CR_ARCH_X64)
|
||||
# define DLL_GIVEFNPTRSTODLL CR_EXPORT void CR_STDCALL
|
||||
# endif
|
||||
#elif defined(CR_LINUX) || defined (CR_OSX) || defined (CR_ANDROID)
|
||||
# define DLL_GIVEFNPTRSTODLL CR_EXPORT void
|
||||
#endif
|
||||
|
||||
DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t *pGlobals) {
|
||||
DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t *glob) {
|
||||
// this is the very first function that is called in the game DLL by the game. Its purpose
|
||||
// is to set the functions interfacing up, by exchanging the functionTable function list
|
||||
// along with a pointer to the engine's global variables structure pGlobals, with the game
|
||||
|
|
@ -937,12 +934,12 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
|
||||
// get the engine functions from the game...
|
||||
memcpy (&engfuncs, functionTable, sizeof (enginefuncs_t));
|
||||
globals = pGlobals;
|
||||
globals = glob;
|
||||
|
||||
if (game.postload ()) {
|
||||
return;
|
||||
}
|
||||
auto api_GiveFnptrsToDll = game.lib ().resolve <void (CR_STDCALL *) (enginefuncs_t *, globalvars_t *)> (__FUNCTION__);
|
||||
auto api_GiveFnptrsToDll = game.lib ().resolve <decltype (&GiveFnptrsToDll)> (__FUNCTION__);
|
||||
|
||||
if (!api_GiveFnptrsToDll) {
|
||||
logger.fatal ("Could not resolve symbol \"%s\" in the game dll.", __FUNCTION__);
|
||||
|
|
@ -953,9 +950,7 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
ents.initialize ();
|
||||
|
||||
// give the engine functions to the other DLL...
|
||||
if (api_GiveFnptrsToDll) {
|
||||
api_GiveFnptrsToDll (functionTable, pGlobals);
|
||||
}
|
||||
api_GiveFnptrsToDll (functionTable, glob);
|
||||
}
|
||||
|
||||
// add linkents for android
|
||||
|
|
@ -1,40 +1,47 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_autovacate ("yb_autovacate", "1", "Kick bots to automatically make room for human players.");
|
||||
ConVar yb_bind_menu_key ("yb_bind_menu_key", "=", "Bind's specified key for openining bots menu.", false);
|
||||
ConVar cv_autovacate ("ub_autovacate", "1", "Kick bots to automatically make room for human players.");
|
||||
ConVar cv_bind_menu_key ("ub_bind_menu_key", "=", "Bind's specified key for opening bots menu.", false);
|
||||
|
||||
ConVar yb_quota ("yb_quota", "0", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar yb_quota_mode ("yb_quota_mode", "normal", "Specifies the type of quota.\nAllowed values: 'normal', 'fill', and 'match'.\nIf 'fill', the server will adjust bots to keep N players in the game, where N is yb_quota.\nIf 'match', the server will maintain a 1:N ratio of humans to bots, where N is yb_quota_match.", false);
|
||||
ConVar yb_quota_match ("yb_quota_match", "0", "Number of players to match if yb_quota_mode set to 'match'", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar yb_think_fps ("yb_think_fps", "30.0", "Specifies hou many times per second bot code will run.", true, 30.0f, 90.0f);
|
||||
ConVar yb_autokill_delay ("yb_autokill_delay", "0.0", "Specifies amount of time in seconds when bots will be killed if no humans left alive.", true, 0.0f, 90.0f);
|
||||
ConVar cv_quota ("ub_quota", "0", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar cv_quota_mode ("ub_quota_mode", "normal", "Specifies the type of quota.\nAllowed values: 'normal', 'fill', and 'match'.\nIf 'fill', the server will adjust bots to keep N players in the game, where N is ub_quota.\nIf 'match', the server will maintain a 1:N ratio of humans to bots, where N is ub_quota_match.", false);
|
||||
ConVar cv_quota_match ("ub_quota_match", "0", "Number of players to match if ub_quota_mode set to 'match'", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
ConVar cv_think_fps ("ub_think_fps", "30.0", "Specifies how many times per second bot code will run.", true, 30.0f, 90.0f);
|
||||
ConVar cv_autokill_delay ("ub_autokill_delay", "0.0", "Specifies amount of time in seconds when bots will be killed if no humans left alive.", true, 0.0f, 90.0f);
|
||||
|
||||
ConVar yb_join_after_player ("yb_join_after_player", "0", "Sepcifies whether bots should join server, only when at least one human player in game.");
|
||||
ConVar yb_join_team ("yb_join_team", "any", "Forces all bots to join team specified here.", false);
|
||||
ConVar yb_join_delay ("yb_join_delay", "5.0", "Specifies after how many seconds bots should start to join the game after the changelevel.", true, 0.0f, 30.0f);
|
||||
ConVar cv_join_after_player ("ub_join_after_player", "0", "Specifies whether bots should join server, only when at least one human player in game.");
|
||||
ConVar cv_join_team ("ub_join_team", "any", "Forces all bots to join team specified here.", false);
|
||||
ConVar cv_join_delay ("ub_join_delay", "5.0", "Specifies after how many seconds bots should start to join the game after the changelevel.", true, 0.0f, 30.0f);
|
||||
|
||||
ConVar yb_name_prefix ("yb_name_prefix", "", "All the bot names will be prefixed with string specified with this cvar.", false);
|
||||
ConVar yb_difficulty ("yb_difficulty", "4", "All bots difficulty level. Chaning at runtime will affect already created bots.", true, 0.0f, 4.0f);
|
||||
ConVar cv_name_prefix ("ub_name_prefix", "", "All the bot names will be prefixed with string specified with this cvar.", false);
|
||||
ConVar cv_difficulty ("ub_difficulty", "4", "All bots difficulty level. Changing at runtime will affect already created bots.", true, 0.0f, 4.0f);
|
||||
|
||||
ConVar yb_show_avatars ("yb_show_avatars", "1", "Enables or disabels displaying bot avatars in front of their names in scoreboard. Note, that is currently you can see only avatars of your steam friends.");
|
||||
ConVar yb_show_latency ("yb_show_latency", "2", "Enables latency display in scoreboard.\nAllowed values: '0', '1', '2'.\nIf '0', there is nothing displayed.\nIf '1', there is a 'BOT' is displayed.\nIf '2' fake ping is displayed.", true, 0.0f, 2.0f);
|
||||
ConVar cv_show_avatars ("ub_show_avatars", "1", "Enables or disabels displaying bot avatars in front of their names in scoreboard. Note, that is currently you can see only avatars of your steam friends.");
|
||||
ConVar cv_show_latency ("ub_show_latency", "2", "Enables latency display in scoreboard.\nAllowed values: '0', '1', '2'.\nIf '0', there is nothing displayed.\nIf '1', there is a 'BOT' is displayed.\nIf '2' fake ping is displayed.", true, 0.0f, 2.0f);
|
||||
|
||||
ConVar yb_language ("yb_language", "en", "Specifies the language for bot messages and menus.", false);
|
||||
ConVar yb_ignore_cvars_on_changelevel ("yb_ignore_cvars_on_changelevel", "yb_quota,yb_autovacate", "Specifies comma separated list of bot cvars, that will not be overriten by config on changelevel.", false);
|
||||
ConVar cv_language ("ub_language", "en", "Specifies the language for bot messages and menus.", false);
|
||||
ConVar cv_ignore_cvars_on_changelevel ("ub_ignore_cvars_on_changelevel", "ub_quota,ub_autovacate", "Specifies comma separated list of bot cvars, that will not be overriten by config on changelevel.", false);
|
||||
|
||||
ConVar mp_limitteams ("mp_limitteams", nullptr, Var::NoRegister);
|
||||
ConVar mp_autoteambalance ("mp_autoteambalance", nullptr, Var::NoRegister);
|
||||
ConVar mp_roundtime ("mp_roundtime", nullptr, Var::NoRegister);
|
||||
ConVar mp_timelimit ("mp_timelimit", nullptr, Var::NoRegister);
|
||||
ConVar mp_freezetime ("mp_freezetime", nullptr, Var::NoRegister, true, "0");
|
||||
ConVar mp_limitteams ("mp_limitteams", nullptr, Var::GameRef);
|
||||
ConVar mp_autoteambalance ("mp_autoteambalance", nullptr, Var::GameRef);
|
||||
ConVar mp_roundtime ("mp_roundtime", nullptr, Var::GameRef);
|
||||
ConVar mp_timelimit ("mp_timelimit", nullptr, Var::GameRef);
|
||||
ConVar mp_freezetime ("mp_freezetime", nullptr, Var::GameRef, true, "0");
|
||||
|
||||
BotManager::BotManager () {
|
||||
// this is a bot manager class constructor
|
||||
|
|
@ -113,20 +120,20 @@ void BotManager::touchKillerEntity (Bot *bot) {
|
|||
kv.szClassName = const_cast <char *> (prop.classname.chars ());
|
||||
kv.szKeyName = "damagetype";
|
||||
kv.szValue = const_cast <char *> (strings.format ("%d", cr::bit (4)));
|
||||
kv.fHandled = false;
|
||||
kv.fHandled = HLFalse;
|
||||
|
||||
MDLL_KeyValue (m_killerEntity, &kv);
|
||||
MDLL_Touch (m_killerEntity, bot->ent ());
|
||||
}
|
||||
|
||||
void BotManager::execGameEntity (entvars_t *vars) {
|
||||
void BotManager::execGameEntity (edict_t *ent) {
|
||||
// this function calls gamedll player() function, in case to create player entity in game
|
||||
|
||||
if (game.is (GameFlags::Metamod)) {
|
||||
CALL_GAME_ENTITY (PLID, "player", vars);
|
||||
CALL_GAME_ENTITY (PLID, "player", &ent->v);
|
||||
return;
|
||||
}
|
||||
ents.getPlayerFunction () (vars);
|
||||
ents.callPlayerFunction (ent);
|
||||
}
|
||||
|
||||
void BotManager::forEach (ForEachBot handler) {
|
||||
|
|
@ -137,7 +144,7 @@ void BotManager::forEach (ForEachBot handler) {
|
|||
}
|
||||
}
|
||||
|
||||
BotCreateResult BotManager::create (const String &name, int difficulty, int personality, int team, int member) {
|
||||
BotCreateResult BotManager::create (StringRef name, int difficulty, int personality, int team, int member) {
|
||||
// this function completely prepares bot entity (edict) for creation, creates team, difficulty, sets named etc, and
|
||||
// then sends result to bot constructor
|
||||
|
||||
|
|
@ -160,11 +167,11 @@ BotCreateResult BotManager::create (const String &name, int difficulty, int pers
|
|||
return BotCreateResult::TeamStacked;
|
||||
}
|
||||
if (difficulty < 0 || difficulty > 4) {
|
||||
difficulty = yb_difficulty.int_ ();
|
||||
difficulty = cv_difficulty.int_ ();
|
||||
|
||||
if (difficulty < 0 || difficulty > 4) {
|
||||
difficulty = rg.int_ (3, 4);
|
||||
yb_difficulty.set (difficulty);
|
||||
cv_difficulty.set (difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -199,9 +206,9 @@ BotCreateResult BotManager::create (const String &name, int difficulty, int pers
|
|||
resultName = name;
|
||||
}
|
||||
|
||||
if (!strings.isEmpty (yb_name_prefix.str ())) {
|
||||
if (!strings.isEmpty (cv_name_prefix.str ())) {
|
||||
String prefixed; // temp buffer for storing modified name
|
||||
prefixed.assignf ("%s %s", yb_name_prefix.str (), resultName.chars ());
|
||||
prefixed.assignf ("%s %s", cv_name_prefix.str (), resultName);
|
||||
|
||||
// buffer has been modified, copy to real name
|
||||
resultName = cr::move (prefixed);
|
||||
|
|
@ -264,16 +271,9 @@ void BotManager::frame () {
|
|||
for (const auto &bot : m_bots) {
|
||||
bot->frame ();
|
||||
}
|
||||
|
||||
// select leader each team somewhere in round start
|
||||
if (m_timeRoundStart + 5.0f > game.time () && m_timeRoundStart + 10.0f < game.time ()) {
|
||||
for (int team = 0; team < kGameTeamNum; ++team) {
|
||||
selectLeaders (team, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BotManager::addbot (const String &name, int difficulty, int personality, int team, int member, bool manual) {
|
||||
void BotManager::addbot (StringRef name, int difficulty, int personality, int team, int member, bool manual) {
|
||||
// this function putting bot creation process to queue to prevent engine crashes
|
||||
|
||||
BotRequest request {};
|
||||
|
|
@ -290,13 +290,13 @@ void BotManager::addbot (const String &name, int difficulty, int personality, in
|
|||
m_addRequests.push (cr::move (request));
|
||||
}
|
||||
|
||||
void BotManager::addbot (const String &name, const String &difficulty, const String &personality, const String &team, const String &member, bool manual) {
|
||||
void BotManager::addbot (StringRef name, StringRef difficulty, StringRef personality, StringRef team, StringRef member, bool manual) {
|
||||
// this function is same as the function above, but accept as parameters string instead of integers
|
||||
|
||||
BotRequest request {};
|
||||
const String &any = "*";
|
||||
StringRef any = "*";
|
||||
|
||||
request.name = (name.empty () || name == any) ? String ("\0") : name;
|
||||
request.name = (name.empty () || name == any) ? StringRef ("\0") : name;
|
||||
request.difficulty = (difficulty.empty () || difficulty == any) ? -1 : difficulty.int_ ();
|
||||
request.team = (team.empty () || team == any) ? -1 : team.int_ ();
|
||||
request.member = (member.empty () || member == any) ? -1 : member.int_ ();
|
||||
|
|
@ -311,10 +311,10 @@ void BotManager::maintainQuota () {
|
|||
// while creation process in process.
|
||||
|
||||
if (graph.length () < 1 || graph.hasChanged ()) {
|
||||
if (yb_quota.int_ () > 0) {
|
||||
if (cv_quota.int_ () > 0) {
|
||||
ctrl.msg ("There is no graph found. Cannot create bot.");
|
||||
}
|
||||
yb_quota.set (0);
|
||||
cv_quota.set (0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -324,23 +324,23 @@ void BotManager::maintainQuota () {
|
|||
const BotCreateResult callResult = create (last.name, last.difficulty, last.personality, last.team, last.member);
|
||||
|
||||
if (last.manual) {
|
||||
yb_quota.set (yb_quota.int_ () + 1);
|
||||
cv_quota.set (cv_quota.int_ () + 1);
|
||||
}
|
||||
|
||||
// check the result of creation
|
||||
if (callResult == BotCreateResult::GraphError) {
|
||||
m_addRequests.clear (); // something wrong with graph, reset tab of creation
|
||||
yb_quota.set (0); // reset quota
|
||||
cv_quota.set (0); // reset quota
|
||||
}
|
||||
else if (callResult == BotCreateResult::MaxPlayersReached) {
|
||||
m_addRequests.clear (); // maximum players reached, so set quota to maximum players
|
||||
yb_quota.set (getBotCount ());
|
||||
cv_quota.set (getBotCount ());
|
||||
}
|
||||
else if (callResult == BotCreateResult::TeamStacked) {
|
||||
ctrl.msg ("Could not add bot to the game: Team is stacked (to disable this check, set mp_limitteams and mp_autoteambalance to zero and restart the round)");
|
||||
|
||||
m_addRequests.clear ();
|
||||
yb_quota.set (getBotCount ());
|
||||
cv_quota.set (getBotCount ());
|
||||
}
|
||||
m_maintainTime = game.time () + 0.10f;
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ void BotManager::maintainQuota () {
|
|||
if (m_quotaMaintainTime > game.time ()) {
|
||||
return;
|
||||
}
|
||||
yb_quota.set (cr::clamp <int> (yb_quota.int_ (), 0, game.maxClients ()));
|
||||
cv_quota.set (cr::clamp <int> (cv_quota.int_ (), 0, game.maxClients ()));
|
||||
|
||||
int totalHumansInGame = getHumansCount ();
|
||||
int humanPlayersInGame = getHumansCount (true);
|
||||
|
|
@ -358,24 +358,24 @@ void BotManager::maintainQuota () {
|
|||
return;
|
||||
}
|
||||
|
||||
int desiredBotCount = yb_quota.int_ ();
|
||||
int desiredBotCount = cv_quota.int_ ();
|
||||
int botsInGame = getBotCount ();
|
||||
|
||||
if (strings.matches (yb_quota_mode.str (), "fill")) {
|
||||
if (strings.matches (cv_quota_mode.str (), "fill")) {
|
||||
botsInGame += humanPlayersInGame;
|
||||
}
|
||||
else if (strings.matches (yb_quota_mode.str (), "match")) {
|
||||
int detectQuotaMatch = yb_quota_match.int_ () == 0 ? yb_quota.int_ () : yb_quota_match.int_ ();
|
||||
else if (strings.matches (cv_quota_mode.str (), "match")) {
|
||||
int detectQuotaMatch = cv_quota_match.int_ () == 0 ? cv_quota.int_ () : cv_quota_match.int_ ();
|
||||
|
||||
desiredBotCount = cr::max <int> (0, detectQuotaMatch * humanPlayersInGame);
|
||||
}
|
||||
|
||||
if (yb_join_after_player.bool_ () && humanPlayersInGame == 0) {
|
||||
if (cv_join_after_player.bool_ () && humanPlayersInGame == 0) {
|
||||
desiredBotCount = 0;
|
||||
}
|
||||
int maxClients = game.maxClients ();
|
||||
|
||||
if (yb_autovacate.bool_ ()) {
|
||||
if (cv_autovacate.bool_ ()) {
|
||||
desiredBotCount = cr::min <int> (desiredBotCount, maxClients - (humanPlayersInGame + 1));
|
||||
}
|
||||
else {
|
||||
|
|
@ -413,8 +413,18 @@ void BotManager::maintainQuota () {
|
|||
m_quotaMaintainTime = game.time () + 0.40f;
|
||||
}
|
||||
|
||||
void BotManager::maintainLeaders () {
|
||||
|
||||
// select leader each team somewhere in round start
|
||||
if (m_timeRoundStart + 5.0f > game.time () && m_timeRoundStart + 10.0f < game.time ()) {
|
||||
for (int team = 0; team < kGameTeamNum; ++team) {
|
||||
selectLeaders (team, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BotManager::maintainAutoKill () {
|
||||
const float killDelay = yb_autokill_delay.float_ ();
|
||||
const float killDelay = cv_autokill_delay.float_ ();
|
||||
|
||||
if (killDelay < 1.0f || m_roundOver) {
|
||||
return;
|
||||
|
|
@ -506,15 +516,15 @@ void BotManager::resetFilters () {
|
|||
|
||||
void BotManager::decrementQuota (int by) {
|
||||
if (by != 0) {
|
||||
yb_quota.set (cr::clamp <int> (yb_quota.int_ () - by, 0, yb_quota.int_ ()));
|
||||
cv_quota.set (cr::clamp <int> (cv_quota.int_ () - by, 0, cv_quota.int_ ()));
|
||||
return;
|
||||
}
|
||||
yb_quota.set (0);
|
||||
cv_quota.set (0);
|
||||
}
|
||||
|
||||
void BotManager::initQuota () {
|
||||
m_maintainTime = game.time () + yb_join_delay.float_ ();
|
||||
m_quotaMaintainTime = game.time () + yb_join_delay.float_ ();
|
||||
m_maintainTime = game.time () + cv_join_delay.float_ ();
|
||||
m_quotaMaintainTime = game.time () + cv_join_delay.float_ ();
|
||||
|
||||
m_addRequests.clear ();
|
||||
}
|
||||
|
|
@ -523,7 +533,7 @@ void BotManager::serverFill (int selection, int personality, int difficulty, int
|
|||
// this function fill server with bots, with specified team & personality
|
||||
|
||||
// always keep one slot
|
||||
int maxClients = yb_autovacate.bool_ () ? game.maxClients () - 1 - (game.isDedicated () ? 0 : getHumansCount ()) : game.maxClients ();
|
||||
int maxClients = cv_autovacate.bool_ () ? game.maxClients () - 1 - (game.isDedicated () ? 0 : getHumansCount ()) : game.maxClients ();
|
||||
|
||||
if (getBotCount () >= maxClients - getHumansCount ()) {
|
||||
return;
|
||||
|
|
@ -546,9 +556,9 @@ void BotManager::serverFill (int selection, int personality, int difficulty, int
|
|||
}
|
||||
|
||||
void BotManager::kickEveryone (bool instant, bool zeroQuota) {
|
||||
// this function drops all bot clients from server (this function removes only yapb's)`q
|
||||
// this function drops all bot clients from server (this function removes only yapb's)
|
||||
|
||||
if (yb_quota.bool_ ()) {
|
||||
if (cv_quota.bool_ ()) {
|
||||
ctrl.msg ("Bots are removed from server.");
|
||||
}
|
||||
|
||||
|
|
@ -672,7 +682,7 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
|
|||
m_lastWinner = winner;
|
||||
m_roundOver = true;
|
||||
|
||||
if (yb_radio_mode.int_ () != 2) {
|
||||
if (cv_radio_mode.int_ () != 2) {
|
||||
return;
|
||||
}
|
||||
auto notify = findAliveBot ();
|
||||
|
|
@ -723,7 +733,7 @@ void BotManager::setWeaponMode (int selection) {
|
|||
tab[i].teamStandard = std[selection][i];
|
||||
tab[i].teamAS = as[selection][i];
|
||||
}
|
||||
yb_jasonmode.set (selection == 0 ? 1 : 0);
|
||||
cv_jasonmode.set (selection == 0 ? 1 : 0);
|
||||
|
||||
ctrl.msg ("%s weapon mode selected.", &modes[selection][0]);
|
||||
}
|
||||
|
|
@ -739,17 +749,11 @@ void BotManager::listBots () {
|
|||
ctrl.msg ("%d bots", m_bots.length ());
|
||||
}
|
||||
|
||||
int BotManager::getBotCount () {
|
||||
// this function returns number of yapb's playing on the server
|
||||
|
||||
return m_bots.length ();
|
||||
}
|
||||
|
||||
float BotManager::getConnectionTime (int botId) {
|
||||
float BotManager::getConnectTime (int botId, float original) {
|
||||
// this function get's fake bot player time.
|
||||
|
||||
for (const auto &bot : m_bots) {
|
||||
if (bot->index () == botId) {
|
||||
if (bot->entindex () == botId) {
|
||||
auto current = plat.seconds ();
|
||||
|
||||
if (current - bot->m_joinServerTime > bot->m_playServerTime || current - bot->m_joinServerTime <= 0.0f) {
|
||||
|
|
@ -759,7 +763,7 @@ float BotManager::getConnectionTime (int botId) {
|
|||
return current - bot->m_joinServerTime;
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
return original;
|
||||
}
|
||||
|
||||
Twin <int, int> BotManager::countTeamPlayers () {
|
||||
|
|
@ -799,9 +803,9 @@ void BotManager::updateTeamEconomics (int team, bool setTrue) {
|
|||
// that have not enough money to buy primary (with economics), and if this result higher 80%, player is can't
|
||||
// buy primary weapons.
|
||||
|
||||
extern ConVar yb_economics_rounds;
|
||||
extern ConVar cv_economics_rounds;
|
||||
|
||||
if (setTrue || !yb_economics_rounds.bool_ ()) {
|
||||
if (setTrue || !cv_economics_rounds.bool_ ()) {
|
||||
m_economicsGood[team] = true;
|
||||
return; // don't check economics while economics disable
|
||||
}
|
||||
|
|
@ -836,7 +840,7 @@ void BotManager::updateTeamEconomics (int team, bool setTrue) {
|
|||
}
|
||||
|
||||
void BotManager::updateBotDifficulties () {
|
||||
int difficulty = yb_difficulty.int_ ();
|
||||
int difficulty = cv_difficulty.int_ ();
|
||||
|
||||
if (difficulty != m_lastDifficulty) {
|
||||
|
||||
|
|
@ -872,20 +876,19 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int member) {
|
|||
bot->v.frags = 0;
|
||||
|
||||
// create the player entity by calling MOD's player function
|
||||
bots.execGameEntity (&bot->v);
|
||||
bots.execGameEntity (bot);
|
||||
|
||||
// set all info buffer keys for this bot
|
||||
auto buffer = engfuncs.pfnGetInfoKeyBuffer (bot);
|
||||
engfuncs.pfnSetClientKeyValue (clientIndex, buffer, "_vgui_menus", "0");
|
||||
|
||||
if (!game.is (GameFlags::Legacy)) {
|
||||
|
||||
if (yb_show_latency.int_ () == 1) {
|
||||
if (cv_show_latency.int_ () == 1) {
|
||||
engfuncs.pfnSetClientKeyValue (clientIndex, buffer, "*bot", "1");
|
||||
}
|
||||
auto avatar = conf.getRandomAvatar ();
|
||||
|
||||
if (yb_show_avatars.bool_ () && !avatar.empty ()) {
|
||||
if (cv_show_avatars.bool_ () && !avatar.empty ()) {
|
||||
engfuncs.pfnSetClientKeyValue (clientIndex, buffer, "*sid", avatar.chars ());
|
||||
}
|
||||
}
|
||||
|
|
@ -1041,7 +1044,7 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
|
|||
auto killerTeam = game.getTeam (killer);
|
||||
auto victimTeam = game.getTeam (victim);
|
||||
|
||||
if (yb_radio_mode.int_ () == 2) {
|
||||
if (cv_radio_mode.int_ () == 2) {
|
||||
// need to send congrats on well placed shot
|
||||
for (const auto ¬ify : bots) {
|
||||
if (notify->m_notKilled && killerTeam == notify->m_team && killerTeam != victimTeam && killer != notify->ent () && notify->seesEntity (victim->v.origin)) {
|
||||
|
|
@ -1095,8 +1098,6 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
|
|||
void Bot::newRound () {
|
||||
// this function initializes a bot after creation & at the start of each round
|
||||
|
||||
int i = 0;
|
||||
|
||||
// delete all allocated path nodes
|
||||
clearSearchNodes ();
|
||||
clearRoute ();
|
||||
|
|
@ -1121,11 +1122,11 @@ void Bot::newRound () {
|
|||
m_numFriendsLeft = 0;
|
||||
m_numEnemiesLeft = 0;
|
||||
m_oldButtons = pev->button;
|
||||
m_rechoiceGoalCount = 0;
|
||||
|
||||
for (i = 0; i < 5; ++i) {
|
||||
m_previousNodes[i] = kInvalidNodeIndex;
|
||||
for (auto &node : m_previousNodes) {
|
||||
node = kInvalidNodeIndex;
|
||||
}
|
||||
|
||||
m_navTimeset = game.time ();
|
||||
m_team = game.getTeam (ent ());
|
||||
m_isVIP = false;
|
||||
|
|
@ -1218,9 +1219,10 @@ void Bot::newRound () {
|
|||
|
||||
m_hostages.clear ();
|
||||
|
||||
for (i = 0; i < Chatter::Count; ++i) {
|
||||
m_chatterTimes[i] = kMaxChatterRepeatInteval;
|
||||
for (auto &timer : m_chatterTimes) {
|
||||
timer = kMaxChatterRepeatInteval;
|
||||
}
|
||||
|
||||
m_isReloading = false;
|
||||
m_reloadState = Reload::None;
|
||||
|
||||
|
|
@ -1238,7 +1240,6 @@ void Bot::newRound () {
|
|||
m_blindButton = 0;
|
||||
m_blindTime = 0.0f;
|
||||
m_jumpTime = 0.0f;
|
||||
m_jumpStateTimer = 0.0f;
|
||||
m_jumpFinished = false;
|
||||
m_isStuck = false;
|
||||
|
||||
|
|
@ -1298,20 +1299,30 @@ void Bot::newRound () {
|
|||
m_heardSoundTime = game.time ();
|
||||
|
||||
// clear its message queue
|
||||
for (i = 0; i < 32; ++i) {
|
||||
m_messageQueue[i] = BotMsg::None;
|
||||
for (auto &msg : m_messageQueue) {
|
||||
msg = BotMsg::None;
|
||||
}
|
||||
|
||||
m_actMessageIndex = 0;
|
||||
m_pushMessageIndex = 0;
|
||||
|
||||
// clear last trace
|
||||
for (auto i = 0; i < TraceChannel::Num; ++i) {
|
||||
m_lastTrace[i] = {};
|
||||
m_traceSkip[i] = 0;
|
||||
}
|
||||
|
||||
// and put buying into its message queue
|
||||
pushMsgQueue (BotMsg::Buy);
|
||||
startTask (Task::Normal, TaskPri::Normal, kInvalidNodeIndex, 0.0f, true);
|
||||
|
||||
// restore fake client bit, just in case
|
||||
pev->flags |= FL_FAKECLIENT;
|
||||
|
||||
if (rg.chance (50)) {
|
||||
pushChatterMessage (Chatter::NewRound);
|
||||
}
|
||||
m_updateInterval = game.is (GameFlags::Legacy | GameFlags::Xash3D) ? 0.0f : (1.0f / cr::clamp (yb_think_fps.float_ (), 30.0f, 60.0f));
|
||||
m_updateInterval = game.is (GameFlags::Legacy | GameFlags::Xash3D) ? 0.0f : (1.0f / cr::clamp (cv_think_fps.float_ (), 30.0f, 60.0f));
|
||||
}
|
||||
|
||||
void Bot::kill () {
|
||||
|
|
@ -1325,9 +1336,10 @@ void Bot::kick () {
|
|||
// this function kick off one bot from the server.
|
||||
auto username = pev->netname.chars ();
|
||||
|
||||
if (!(pev->flags & FL_FAKECLIENT) || strings.isEmpty (username)) {
|
||||
if (!(pev->flags & FL_CLIENT) || strings.isEmpty (username)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear fakeclient bit
|
||||
pev->flags &= ~FL_FAKECLIENT;
|
||||
|
||||
|
|
@ -1371,7 +1383,7 @@ void Bot::updateTeamJoin () {
|
|||
if (m_startAction == BotMsg::TeamSelect) {
|
||||
m_startAction = BotMsg::None; // switch back to idle
|
||||
|
||||
char teamJoin = yb_join_team.str ()[0];
|
||||
char teamJoin = cv_join_team.str ()[0];
|
||||
|
||||
if (teamJoin == 'C' || teamJoin == 'c') {
|
||||
m_wantedTeam = 2;
|
||||
|
|
@ -1494,13 +1506,10 @@ void BotManager::updateActiveGrenade () {
|
|||
// search the map for any type of grenade
|
||||
game.searchEntities ("classname", "grenade", [&] (edict_t *e) {
|
||||
// do not count c4 as a grenade
|
||||
if (strcmp (e->v.model.chars (9), "c4.mdl") == 0) {
|
||||
return EntitySearchResult::Continue;
|
||||
if (strcmp (e->v.model.chars (9), "c4.mdl") != 0) {
|
||||
m_activeGrenades.push (e);
|
||||
}
|
||||
m_activeGrenades.push (e);
|
||||
|
||||
// continue iteration
|
||||
return EntitySearchResult::Continue;
|
||||
return EntitySearchResult::Continue; // continue iteration
|
||||
});
|
||||
m_grenadeUpdateTime = game.time () + 0.25f;
|
||||
}
|
||||
|
|
@ -1518,7 +1527,7 @@ void BotManager::updateIntrestingEntities () {
|
|||
auto classname = e->v.classname.chars ();
|
||||
|
||||
// search for grenades, weaponboxes, weapons, items and armoury entities
|
||||
if (strncmp ("weapon", classname, 6) == 0 || strncmp ("grenade", classname, 7) == 0 || strncmp ("item", classname, 4) == 0 || strncmp ("armoury", classname, 7) == 0) {
|
||||
if (strncmp ("weaponbox", classname, 9) == 0 || strncmp ("grenade", classname, 7) == 0 || strncmp ("item", classname, 4) == 0 || strncmp ("armoury", classname, 7) == 0) {
|
||||
m_intrestingEntities.push (e);
|
||||
}
|
||||
|
||||
|
|
@ -1590,7 +1599,7 @@ void BotManager::selectLeaders (int team, bool reset) {
|
|||
|
||||
// terrorist carrying a bomb needs to have some company
|
||||
if (rg.chance (75)) {
|
||||
if (yb_radio_mode.int_ () == 2) {
|
||||
if (cv_radio_mode.int_ () == 2) {
|
||||
bot->pushChatterMessage (Chatter::GoingToPlantBomb);
|
||||
}
|
||||
else {
|
||||
|
|
@ -1689,9 +1698,10 @@ void BotManager::setBombPlanted (bool isPlanted) {
|
|||
}
|
||||
|
||||
BotConfig::BotConfig () {
|
||||
m_chat.ensure (Chat::Count);
|
||||
m_chatter.ensure (Chatter::Count);
|
||||
m_weaponProps.ensure (kMaxWeapons);
|
||||
m_chat.resize (Chat::Count);
|
||||
m_chatter.resize (Chatter::Count);
|
||||
|
||||
m_weaponProps.resize (kMaxWeapons);
|
||||
}
|
||||
|
||||
void BotConfig::loadConfigs () {
|
||||
|
|
@ -1704,6 +1714,7 @@ void BotConfig::loadConfigs () {
|
|||
loadLanguageConfig ();
|
||||
loadLogosConfig ();
|
||||
loadAvatarsConfig ();
|
||||
loadDifficultyConfig ();
|
||||
}
|
||||
|
||||
void BotConfig::loadMainConfig () {
|
||||
|
|
@ -1725,7 +1736,7 @@ void BotConfig::loadMainConfig () {
|
|||
String line;
|
||||
MemFile file;
|
||||
|
||||
// this is does the same as exec of engine, but not overwriting values of cvars spcified in yb_ignore_cvars_on_changelevel
|
||||
// this is does the same as exec of engine, but not overwriting values of cvars spcified in cv_ignore_cvars_on_changelevel
|
||||
if (util.openConfig ("yapb.cfg", "YaPB main config file is not found.", &file, false)) {
|
||||
while (file.getLine (line)) {
|
||||
line.trim ();
|
||||
|
|
@ -1741,7 +1752,7 @@ void BotConfig::loadMainConfig () {
|
|||
auto keyval = line.split (" ");
|
||||
|
||||
if (keyval.length () > 1) {
|
||||
auto ignore = String (yb_ignore_cvars_on_changelevel.str ()).split (",");
|
||||
auto ignore = String (cv_ignore_cvars_on_changelevel.str ()).split (",");
|
||||
|
||||
auto key = keyval[0].trim ().chars ();
|
||||
auto cvar = engfuncs.pfnCVarGetPointer (key);
|
||||
|
|
@ -1752,7 +1763,7 @@ void BotConfig::loadMainConfig () {
|
|||
if (needsToIgnoreVar (ignore, key) && !strings.matches (value, cvar->string)) {
|
||||
|
||||
// preserve quota number if it's zero
|
||||
if (strings.matches (cvar->name, "yb_quota") && yb_quota.int_ () <= 0) {
|
||||
if (strings.matches (cvar->name, "ub_quota") && cv_quota.int_ () <= 0) {
|
||||
engfuncs.pfnCvar_DirectSet (cvar, value);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1775,13 +1786,13 @@ void BotConfig::loadMainConfig () {
|
|||
firstLoad = false;
|
||||
|
||||
// android is abit hard to play, lower the difficulty by default
|
||||
if (plat.android && yb_difficulty.int_ () > 3) {
|
||||
yb_difficulty.set (3);
|
||||
if (plat.android && cv_difficulty.int_ () > 3) {
|
||||
cv_difficulty.set (3);
|
||||
}
|
||||
|
||||
// bind the correct menu key for bot menu...
|
||||
if (!game.isDedicated () && !strings.isEmpty (yb_bind_menu_key.str ())) {
|
||||
game.serverCommand ("bind \"%s\" \"yb menu\"", yb_bind_menu_key.str ());
|
||||
if (!game.isDedicated () && !strings.isEmpty (cv_bind_menu_key.str ())) {
|
||||
game.serverCommand ("bind \"%s\" \"yb menu\"", cv_bind_menu_key.str ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1803,7 +1814,7 @@ void BotConfig::loadNamesConfig () {
|
|||
}
|
||||
// max botname is 32 characters
|
||||
if (line.length () > 32) {
|
||||
line[32] = '\0';
|
||||
line[32] = kNullChar;
|
||||
}
|
||||
m_botNames.emplace (line, -1);
|
||||
}
|
||||
|
|
@ -1814,11 +1825,11 @@ void BotConfig::loadNamesConfig () {
|
|||
void BotConfig::loadWeaponsConfig () {
|
||||
setupMemoryFiles ();
|
||||
|
||||
auto addWeaponEntries = [] (SmallArray <WeaponInfo> &weapons, bool as, const String &name, const StringArray &data) {
|
||||
auto addWeaponEntries = [] (SmallArray <WeaponInfo> &weapons, bool as, StringRef name, const StringArray &data) {
|
||||
|
||||
// we're have null terminator element in weapons array...
|
||||
if (data.length () + 1 != weapons.length ()) {
|
||||
logger.error ("%s entry in weapons config is not valid or malformed (%d/%d).", name.chars (), data.length (), weapons.length ());
|
||||
logger.error ("%s entry in weapons config is not valid or malformed (%d/%d).", name, data.length (), weapons.length ());
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1833,9 +1844,9 @@ void BotConfig::loadWeaponsConfig () {
|
|||
}
|
||||
};
|
||||
|
||||
auto addIntEntries = [] (SmallArray <int32> &to, const String &name, const StringArray &data) {
|
||||
auto addIntEntries = [] (SmallArray <int32> &to, StringRef name, const StringArray &data) {
|
||||
if (data.length () != to.length ()) {
|
||||
logger.error ("%s entry in weapons config is not valid or malformed (%d/%d).", name.chars (), data.length (), to.length ());
|
||||
logger.error ("%s entry in weapons config is not valid or malformed (%d/%d).", name, data.length (), to.length ());
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1847,7 +1858,7 @@ void BotConfig::loadWeaponsConfig () {
|
|||
MemFile file;
|
||||
|
||||
// weapon data initialization
|
||||
if (util.openConfig ("general.cfg", "General configuration file not found. Loading defaults", &file)) {
|
||||
if (util.openConfig ("weapon.cfg", "Weapon configuration file not found. Loading defaults", &file)) {
|
||||
while (file.getLine (line)) {
|
||||
line.trim ();
|
||||
|
||||
|
|
@ -1899,7 +1910,7 @@ void BotConfig::loadChatterConfig () {
|
|||
MemFile file;
|
||||
|
||||
// chatter initialization
|
||||
if (game.is (GameFlags::HasBotVoice) && yb_radio_mode.int_ () == 2 && util.openConfig ("chatter.cfg", "Couldn't open chatter system configuration", &file)) {
|
||||
if (game.is (GameFlags::HasBotVoice) && cv_radio_mode.int_ () == 2 && util.openConfig ("chatter.cfg", "Couldn't open chatter system configuration", &file)) {
|
||||
m_chatter.clear ();
|
||||
|
||||
struct EventMap {
|
||||
|
|
@ -1986,13 +1997,15 @@ void BotConfig::loadChatterConfig () {
|
|||
if (isCommentLine (line)) {
|
||||
continue;
|
||||
}
|
||||
extern ConVar yb_chatter_path;
|
||||
|
||||
if (line.startsWith ("RewritePath")) {
|
||||
yb_chatter_path.set (line.substr (11).trim ().chars ());
|
||||
StringRef rewriteKey = "RewritePath";
|
||||
StringRef eventKey = "Event";
|
||||
|
||||
if (line.startsWith (rewriteKey)) {
|
||||
cv_chatter_path.set (line.substr (rewriteKey.length ()).trim ().chars ());
|
||||
}
|
||||
else if (line.startsWith ("Event")) {
|
||||
auto items = line.substr (5).split ("=");
|
||||
else if (line.startsWith (eventKey)) {
|
||||
auto items = line.substr (eventKey.length ()).split ("=");
|
||||
|
||||
if (items.length () != 2) {
|
||||
logger.error ("Error in chatter config file syntax... Please correct all errors.");
|
||||
|
|
@ -2025,7 +2038,7 @@ void BotConfig::loadChatterConfig () {
|
|||
file.close ();
|
||||
}
|
||||
else {
|
||||
yb_radio_mode.set (1);
|
||||
cv_radio_mode.set (1);
|
||||
logger.message ("Bots chatter communication disabled.");
|
||||
}
|
||||
}
|
||||
|
|
@ -2091,6 +2104,7 @@ void BotConfig::loadChatConfig () {
|
|||
|
||||
if (chat != nullptr) {
|
||||
chat->push (line);
|
||||
|
||||
}
|
||||
else {
|
||||
if (line.startsWith ("@KEY")) {
|
||||
|
|
@ -2124,7 +2138,7 @@ void BotConfig::loadChatConfig () {
|
|||
file.close ();
|
||||
}
|
||||
else {
|
||||
yb_chat.set (0);
|
||||
cv_chat.set (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2172,7 +2186,7 @@ void BotConfig::loadLanguageConfig () {
|
|||
}
|
||||
file.close ();
|
||||
}
|
||||
else if (strcmp (yb_language.str (), "en") != 0) {
|
||||
else if (strcmp (cv_language.str (), "en") != 0) {
|
||||
logger.error ("Couldn't load language configuration");
|
||||
}
|
||||
}
|
||||
|
|
@ -2188,7 +2202,7 @@ void BotConfig::loadAvatarsConfig () {
|
|||
MemFile file;
|
||||
|
||||
// avatars inititalization
|
||||
if (util.openConfig ("avatars.cfg", "Avatars config file not found. Avatars will not display.", &file)) {
|
||||
if (util.openConfig ("avatars.cfg", "Avatars config file not found. Avatars will not be displayed.", &file)) {
|
||||
m_avatars.clear ();
|
||||
|
||||
while (file.getLine (line)) {
|
||||
|
|
@ -2200,6 +2214,88 @@ void BotConfig::loadAvatarsConfig () {
|
|||
}
|
||||
}
|
||||
|
||||
void BotConfig::loadDifficultyConfig () {
|
||||
setupMemoryFiles ();
|
||||
|
||||
String line;
|
||||
MemFile file;
|
||||
|
||||
// initialize defaults
|
||||
m_difficulty[Difficulty::Noob] = {
|
||||
{ 0.8f, 1.0f }, 5, 0, 0
|
||||
};
|
||||
|
||||
m_difficulty[Difficulty::Easy] = {
|
||||
{ 0.6f, 0.8f }, 30, 10, 10
|
||||
};
|
||||
|
||||
m_difficulty[Difficulty::Normal] = {
|
||||
{ 0.4f, 0.6f }, 50, 30, 40
|
||||
};
|
||||
|
||||
m_difficulty[Difficulty::Hard] = {
|
||||
{ 0.2f, 0.4f }, 75, 60, 70
|
||||
};
|
||||
|
||||
m_difficulty[Difficulty::Expert] = {
|
||||
{ 0.1f, 0.2f }, 100, 90, 90
|
||||
};
|
||||
|
||||
// currently, mindelay, maxdelay, headprob, seenthruprob, heardthruprob
|
||||
constexpr uint32 kMaxDifficultyValues = 5;
|
||||
|
||||
// helper for parsing each level
|
||||
auto parseLevel = [&] (int32 level, StringRef data) {
|
||||
auto values = data.split <String> (",");
|
||||
|
||||
if (values.length () != kMaxDifficultyValues) {
|
||||
logger.error ("Bad value for difficulty level #%d.", level);
|
||||
return;
|
||||
}
|
||||
auto diff = &m_difficulty[level];
|
||||
|
||||
diff->reaction[0] = values[0].float_ ();
|
||||
diff->reaction[1] = values[1].float_ ();
|
||||
diff->headshotPct = values[2].int_ ();
|
||||
diff->seenThruPct = values[3].int_ ();
|
||||
diff->hearThruPct = values[4].int_ ();
|
||||
};
|
||||
|
||||
// avatars inititalization
|
||||
if (util.openConfig ("difficulty.cfg", "Difficulty config file not found. Defaults loaded.", &file)) {
|
||||
|
||||
while (file.getLine (line)) {
|
||||
if (isCommentLine (line)) {
|
||||
continue;
|
||||
}
|
||||
auto items = line.split ("=");
|
||||
|
||||
if (items.length () != 2) {
|
||||
logger.error ("Error in difficulty config file syntax... Please correct all errors.");
|
||||
continue;
|
||||
}
|
||||
auto key = items[0].trim ();
|
||||
|
||||
// get our keys
|
||||
if (key == "Noob") {
|
||||
parseLevel (Difficulty::Noob, items[1]);
|
||||
}
|
||||
else if (key == "Easy") {
|
||||
parseLevel (Difficulty::Easy, items[1]);
|
||||
}
|
||||
else if (key == "Normal") {
|
||||
parseLevel (Difficulty::Normal, items[1]);
|
||||
}
|
||||
else if (key == "Hard") {
|
||||
parseLevel (Difficulty::Hard, items[1]);
|
||||
}
|
||||
else if (key == "Expert") {
|
||||
parseLevel (Difficulty::Expert, items[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BotConfig::loadLogosConfig () {
|
||||
setupMemoryFiles ();
|
||||
|
||||
|
|
@ -2218,7 +2314,7 @@ void BotConfig::loadLogosConfig () {
|
|||
}
|
||||
}
|
||||
else {
|
||||
m_logos = cr::move (String ("{biohaz;{graf003;{graf004;{graf005;{lambda06;{target;{hand1;{spit2;{bloodhand6;{foot_l;{foot_r").split (";"));
|
||||
m_logos = cr::move (String { "{biohaz;{graf003;{graf004;{graf005;{lambda06;{target;{hand1;{spit2;{bloodhand6;{foot_l;{foot_r" }.split (";"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2230,12 +2326,12 @@ void BotConfig::setupMemoryFiles () {
|
|||
};
|
||||
|
||||
auto wrapFreeFile = [] (void *buffer) {
|
||||
return engfuncs.pfnFreeFile (buffer);
|
||||
engfuncs.pfnFreeFile (buffer);
|
||||
};
|
||||
|
||||
if (setMemoryPointers) {
|
||||
MemFileStorage::get ().initizalize (wrapLoadFile, wrapFreeFile);
|
||||
setMemoryPointers = true;
|
||||
MemFileStorage::instance ().initizalize (wrapLoadFile, wrapFreeFile);
|
||||
setMemoryPointers = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2322,17 +2418,17 @@ WeaponInfo &BotConfig::findWeaponById (const int id) {
|
|||
return m_weapons.at (0);
|
||||
}
|
||||
|
||||
|
||||
const char *BotConfig::translate (const char *input) {
|
||||
const char *BotConfig::translate (StringRef input) {
|
||||
// this function translate input string into needed language
|
||||
|
||||
if (game.isDedicated ()) {
|
||||
return input;
|
||||
return input.chars ();
|
||||
}
|
||||
static String result;
|
||||
result.clear ();
|
||||
|
||||
if (m_language.find (input, result)) {
|
||||
return result.chars ();
|
||||
}
|
||||
return input; // nothing found
|
||||
return input.chars (); // nothing found
|
||||
}
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
|
@ -62,9 +69,11 @@ void MessageDispatcher::netMsgTextMsg () {
|
|||
for (const auto ¬ify : bots) {
|
||||
if (notify->m_notKilled) {
|
||||
notify->clearSearchNodes ();
|
||||
notify->clearTasks ();
|
||||
|
||||
if (yb_radio_mode.int_ () == 2 && rg.chance (55) && notify->m_team == Team::CT) {
|
||||
// clear only camp tasks
|
||||
notify->clearTask (Task::Camp);
|
||||
|
||||
if (cv_radio_mode.int_ () == 2 && rg.chance (55) && notify->m_team == Team::CT) {
|
||||
notify->pushChatterMessage (Chatter::WhereIsTheC4);
|
||||
}
|
||||
}
|
||||
|
|
@ -170,6 +179,9 @@ void MessageDispatcher::netMsgCurWeapon () {
|
|||
void MessageDispatcher::netMsgAmmoX () {
|
||||
// this message is sent whenever ammo amounts are adjusted (up or down). NOTE: Logging reveals that CS uses it very unreliable!
|
||||
|
||||
#if 1
|
||||
netMsgAmmoPickup ();
|
||||
#else
|
||||
enum args { index = 0, value = 1, min = 2 };
|
||||
|
||||
// check the minimum states
|
||||
|
|
@ -177,6 +189,7 @@ void MessageDispatcher::netMsgAmmoX () {
|
|||
return;
|
||||
}
|
||||
m_bot->m_ammo[m_args[index].long_] = m_args[value].long_; // store it away
|
||||
#endif
|
||||
}
|
||||
|
||||
void MessageDispatcher::netMsgAmmoPickup () {
|
||||
|
|
@ -376,7 +389,7 @@ void MessageDispatcher::netMsgFlashBat () {
|
|||
MessageDispatcher::MessageDispatcher () {
|
||||
|
||||
// register wanted message
|
||||
auto pushWanted = [&] (const String &name, NetMsg id, MsgFunc handler) -> void {
|
||||
auto pushWanted = [&] (StringRef name, NetMsg id, MsgFunc handler) -> void {
|
||||
m_wanted[name] = id;
|
||||
m_handlers[id] = handler;
|
||||
};
|
||||
|
|
@ -450,7 +463,7 @@ MessageDispatcher::MessageDispatcher () {
|
|||
m_teamInfoCache["CT"] = Team::CT;
|
||||
}
|
||||
|
||||
int32 MessageDispatcher::add (const String &name, int32 id) {
|
||||
int32 MessageDispatcher::add (StringRef name, int32 id) {
|
||||
if (!m_wanted.exists (name)) {
|
||||
return id;
|
||||
}
|
||||
|
|
@ -1,15 +1,22 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_whose_your_daddy ("yb_whose_your_daddy", "0", "Enables or disables extra hard difficulty for bots.");
|
||||
ConVar yb_debug_heuristic_type ("yb_debug_heuristic_type", "0", "Selects the heuristic function mode. For debug purposes only.", true, 0.0f, 4.0f);
|
||||
ConVar cv_whose_your_daddy ("ub_whose_your_daddy", "0", "Enables or disables extra hard difficulty for bots.");
|
||||
ConVar cv_debug_heuristic_type ("ub_debug_heuristic_type", "0", "Selects the heuristic function mode. For debug purposes only.", true, 0.0f, 4.0f);
|
||||
|
||||
int Bot::findBestGoal () {
|
||||
|
||||
|
|
@ -209,6 +216,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
|
|||
if (goalChoices[0] == kInvalidNodeIndex) {
|
||||
return m_chosenGoalIndex = rg.int_ (0, graph.length () - 1);
|
||||
}
|
||||
|
||||
bool sorting = false;
|
||||
|
||||
do {
|
||||
|
|
@ -228,7 +236,7 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
|
|||
return m_chosenGoalIndex = goalChoices[0]; // return and store goal
|
||||
}
|
||||
|
||||
void Bot::postprocessGoals (const IntArray &goals, int *result) {
|
||||
void Bot::postprocessGoals (const IntArray &goals, int result[]) {
|
||||
// this function filters the goals, so new goal is not bot's old goal, and array of goals doesn't contains duplicate goals
|
||||
|
||||
int searchCount = 0;
|
||||
|
|
@ -248,7 +256,7 @@ void Bot::postprocessGoals (const IntArray &goals, int *result) {
|
|||
}
|
||||
|
||||
bool Bot::hasActiveGoal () {
|
||||
int goal = getTask ()->data;
|
||||
auto goal = getTask ()->data;
|
||||
|
||||
if (goal == kInvalidNodeIndex) { // not decided about a goal
|
||||
return false;
|
||||
|
|
@ -357,12 +365,13 @@ bool Bot::doPlayerAvoidance (const Vector &normal) {
|
|||
}
|
||||
|
||||
void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
||||
m_isStuck = false;
|
||||
|
||||
// if avoiding someone do not consider stuck
|
||||
TraceResult tr {};
|
||||
doPlayerAvoidance (dirNormal);
|
||||
|
||||
m_isStuck = false;
|
||||
|
||||
// Standing still, no need to check?
|
||||
// FIXME: doesn't care for ladder movement (handled separately) should be included in some way
|
||||
if ((m_moveSpeed >= 10.0f || m_strafeSpeed >= 10.0f) && m_lastCollTime < game.time () && m_seeEnemyTime + 0.8f < game.time () && getCurrentTaskId () != Task::Attack) {
|
||||
|
|
@ -380,7 +389,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
else {
|
||||
// test if there's something ahead blocking the way
|
||||
if (cantMoveForward (dirNormal, &tr) && !isOnLadder ()) {
|
||||
if (m_firstCollideTime == 0.0f) {
|
||||
if (cr::fzero (m_firstCollideTime)) {
|
||||
m_firstCollideTime = game.time () + 0.2f;
|
||||
}
|
||||
else if (m_firstCollideTime <= game.time ()) {
|
||||
|
|
@ -406,11 +415,8 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
return;
|
||||
}
|
||||
|
||||
// bot is stuck!
|
||||
Vector src;
|
||||
Vector dst;
|
||||
|
||||
// not yet decided what to do?
|
||||
// bot is stuc, but not yet decided what to do?
|
||||
if (m_collisionState == CollisionState::Undecided) {
|
||||
int bits = 0;
|
||||
|
||||
|
|
@ -421,7 +427,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
bits |= (CollisionProbe::Jump | CollisionProbe::Strafe);
|
||||
}
|
||||
else {
|
||||
bits |= (CollisionProbe::Strafe | (m_jumpStateTimer < game.time () ? CollisionProbe::Jump : 0));
|
||||
bits |= (CollisionProbe::Strafe | CollisionProbe::Jump);
|
||||
}
|
||||
|
||||
// collision check allowed if not flying through the air
|
||||
|
|
@ -429,6 +435,8 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
int state[kMaxCollideMoves * 2 + 1];
|
||||
int i = 0;
|
||||
|
||||
Vector src {}, dst {};
|
||||
|
||||
// first 4 entries hold the possible collision states
|
||||
state[i++] = CollisionState::StrafeLeft;
|
||||
state[i++] = CollisionState::StrafeRight;
|
||||
|
|
@ -440,7 +448,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
state[i + 1] = 0;
|
||||
|
||||
// to start strafing, we have to first figure out if the target is on the left side or right side
|
||||
Vector right, forward;
|
||||
Vector right {}, forward {};
|
||||
m_moveAngles.angleVectors (&forward, &right, nullptr);
|
||||
|
||||
const Vector &dirToPoint = (pev->origin - m_destOrigin).normalize2d ();
|
||||
|
|
@ -465,7 +473,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedRight = true;
|
||||
}
|
||||
src = pev->origin - right * 32.0f;
|
||||
|
|
@ -473,7 +481,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
|
||||
game.testHull (src, dst, TraceIgnore::Monsters, head_hull, ent (), &tr);
|
||||
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
blockedLeft = true;
|
||||
}
|
||||
|
||||
|
|
@ -541,7 +549,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
dst = src + dirNormal * 30.0f;
|
||||
game.testLine (src, dst, TraceIgnore::Everything, ent (), &tr);
|
||||
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
state[i] += 10;
|
||||
}
|
||||
}
|
||||
|
|
@ -611,7 +619,6 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
case CollisionState::Jump:
|
||||
if (isOnFloor () || isInWater ()) {
|
||||
pev->button |= IN_JUMP;
|
||||
m_jumpStateTimer = game.time () + rg.float_ (0.7f, 1.5f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -642,9 +649,9 @@ bool Bot::updateNavigation () {
|
|||
findValidNode ();
|
||||
m_pathOrigin = m_path->origin;
|
||||
|
||||
// if wayzone radius non zero vary origin a bit depending on the body angles
|
||||
// if graph node radius non zero vary origin a bit depending on the body angles
|
||||
if (m_path->radius > 0.0f) {
|
||||
m_pathOrigin = m_pathOrigin + Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.float_ (-90.0f, 90.0f)), 0.0f).forward () * rg.float_ (0.0f, m_path->radius);
|
||||
m_pathOrigin += Vector (pev->angles.x, cr::normalizeAngles (pev->angles.y + rg.float_ (-90.0f, 90.0f)), 0.0f).forward () * rg.float_ (0.0f, m_path->radius);
|
||||
}
|
||||
m_navTimeset = game.time ();
|
||||
}
|
||||
|
|
@ -669,7 +676,7 @@ bool Bot::updateNavigation () {
|
|||
m_desiredVelocity = nullptr;
|
||||
}
|
||||
}
|
||||
else if (!yb_jasonmode.bool_ () && m_currentWeapon == Weapon::Knife && isOnFloor ()) {
|
||||
else if (!cv_jasonmode.bool_ () && m_currentWeapon == Weapon::Knife && isOnFloor ()) {
|
||||
selectBestWeapon ();
|
||||
}
|
||||
}
|
||||
|
|
@ -794,6 +801,17 @@ bool Bot::updateNavigation () {
|
|||
desiredDistance = nodeDistance + 1.0f;
|
||||
}
|
||||
|
||||
// this allows us to prevent stupid bot behaviour when he reaches almost end point of this route, but some one (other bot eg)
|
||||
// is sitting there, so the bot is unable to reach the node because of other player on it, and he starts to jumping and so on
|
||||
// here we're clearing task memory data (important!), since task executor may restart goal with one from memory, so this process
|
||||
// will go in cycle, and forcing bot to re-create new route.
|
||||
if (m_pathWalk.hasNext () && m_pathWalk.next () == m_pathWalk.last () && isOccupiedNode (m_pathWalk.next (), true)) {
|
||||
getTask ()->data = kInvalidNodeIndex;
|
||||
clearSearchNodes ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nodeDistance < desiredDistance) {
|
||||
|
||||
// did we reach a destination node?
|
||||
|
|
@ -985,7 +1003,7 @@ bool Bot::updateLiftHandling () {
|
|||
auto button = lookupButton (m_liftEntity->v.targetname.chars ());
|
||||
|
||||
// got a valid button entity ?
|
||||
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && m_liftEntity->v.velocity.z == 0.0f && isOnFloor ()) {
|
||||
if (!game.isNullEntity (button) && pev->groundentity == m_liftEntity && m_buttonPushTime + 1.0f < game.time () && cr::fzero (m_liftEntity->v.velocity.z) && isOnFloor ()) {
|
||||
m_pickupItem = button;
|
||||
m_pickupType = Pickup::Button;
|
||||
|
||||
|
|
@ -995,7 +1013,7 @@ bool Bot::updateLiftHandling () {
|
|||
|
||||
// is lift activated and bot is standing on it and lift is moving ?
|
||||
if (m_liftState == LiftState::LookingButtonInside || m_liftState == LiftState::EnteringIn || m_liftState == LiftState::WaitingForTeammates || m_liftState == LiftState::WaitingFor) {
|
||||
if (pev->groundentity == m_liftEntity && m_liftEntity->v.velocity.z != 0.0f && isOnFloor () && ((graph[m_previousNodes[0]].flags & NodeFlag::Lift) || !game.isNullEntity (m_targetEntity))) {
|
||||
if (pev->groundentity == m_liftEntity && !cr::fzero (m_liftEntity->v.velocity.z) && isOnFloor () && ((graph[m_previousNodes[0]].flags & NodeFlag::Lift) || !game.isNullEntity (m_targetEntity))) {
|
||||
m_liftState = LiftState::TravelingBy;
|
||||
m_liftUsageTime = game.time () + 14.0f;
|
||||
|
||||
|
|
@ -1131,7 +1149,7 @@ bool Bot::updateLiftStates () {
|
|||
}
|
||||
}
|
||||
|
||||
if (m_liftUsageTime < game.time () && m_liftUsageTime != 0.0f) {
|
||||
if (m_liftUsageTime < game.time () && !cr::fzero (m_liftUsageTime)) {
|
||||
m_liftEntity = nullptr;
|
||||
m_liftState = LiftState::None;
|
||||
m_liftUsageTime = 0.0f;
|
||||
|
|
@ -1294,7 +1312,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
float y = cr::abs (start.origin.y - goal.origin.y);
|
||||
float z = cr::abs (start.origin.z - goal.origin.z);
|
||||
|
||||
switch (yb_debug_heuristic_type.int_ ()) {
|
||||
switch (cv_debug_heuristic_type.int_ ()) {
|
||||
case 0:
|
||||
default:
|
||||
return cr::max (cr::max (x, y), z); // chebyshev distance
|
||||
|
|
@ -1310,7 +1328,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
// euclidean based distance
|
||||
float euclidean = cr::powf (cr::powf (x, 2.0f) + cr::powf (y, 2.0f) + cr::powf (z, 2.0f), 0.5f);
|
||||
|
||||
if (yb_debug_heuristic_type.int_ () == 4) {
|
||||
if (cv_debug_heuristic_type.int_ () == 4) {
|
||||
return 1000.0f *(cr::ceilf (euclidean) - euclidean);
|
||||
}
|
||||
return euclidean;
|
||||
|
|
@ -1648,7 +1666,7 @@ float Bot::getReachTime () {
|
|||
if (longTermReachability) {
|
||||
estimatedTime *= 2.0f;
|
||||
}
|
||||
estimatedTime = cr::clamp (estimatedTime, 1.2f, longTermReachability ? 8.0f : 5.0f);
|
||||
estimatedTime = cr::clamp (estimatedTime, 2.0f, longTermReachability ? 8.0f : 5.0f);
|
||||
}
|
||||
return estimatedTime;
|
||||
}
|
||||
|
|
@ -1656,30 +1674,10 @@ float Bot::getReachTime () {
|
|||
void Bot::findValidNode () {
|
||||
// checks if the last node the bot was heading for is still valid
|
||||
|
||||
auto trySelectNewGoal = [&] () {
|
||||
if (m_rechoiceGoalCount > 1) {
|
||||
int newGoal = findBestGoal ();
|
||||
|
||||
m_prevGoalIndex = newGoal;
|
||||
m_chosenGoalIndex = newGoal;
|
||||
getTask ()->data = newGoal;
|
||||
|
||||
// do path finding if it's not the current node
|
||||
if (newGoal != m_currentNodeIndex) {
|
||||
findPath (m_currentNodeIndex, newGoal, m_pathType);
|
||||
}
|
||||
m_rechoiceGoalCount = 0;
|
||||
}
|
||||
else {
|
||||
findBestNearestNode ();
|
||||
++m_rechoiceGoalCount;
|
||||
}
|
||||
};
|
||||
|
||||
// if bot hasn't got a node we need a new one anyway or if time to get there expired get new one as well
|
||||
if (m_currentNodeIndex == kInvalidNodeIndex) {
|
||||
clearSearchNodes ();
|
||||
trySelectNewGoal ();
|
||||
findBestNearestNode ();
|
||||
|
||||
m_pathOrigin = m_path->origin;
|
||||
}
|
||||
|
|
@ -1687,7 +1685,6 @@ void Bot::findValidNode () {
|
|||
|
||||
// increase danager for both teams
|
||||
for (int team = Team::Terrorist; team < kGameTeamNum; ++team) {
|
||||
|
||||
int damageValue = graph.getDangerDamage (team, m_currentNodeIndex, m_currentNodeIndex);
|
||||
damageValue = cr::clamp (damageValue + 100, 0, kMaxPracticeDamageValue);
|
||||
|
||||
|
|
@ -1702,9 +1699,8 @@ void Bot::findValidNode () {
|
|||
}
|
||||
graph.setDangerDamage (m_team, m_currentNodeIndex, m_currentNodeIndex, damageValue);
|
||||
}
|
||||
|
||||
clearSearchNodes ();
|
||||
trySelectNewGoal ();
|
||||
findBestNearestNode ();
|
||||
|
||||
m_pathOrigin = m_path->origin;
|
||||
}
|
||||
|
|
@ -1764,26 +1760,27 @@ int Bot::findBombNode () {
|
|||
|
||||
auto &goals = graph.m_goalPoints;
|
||||
|
||||
auto bomb = graph.getBombOrigin ();
|
||||
auto audible = isBombAudible ();
|
||||
|
||||
if (!audible.empty ()) {
|
||||
m_bombSearchOverridden = true;
|
||||
return graph.getNearest (audible, 240.0f);
|
||||
}
|
||||
else if (goals.empty ()) {
|
||||
return graph.getNearest (bomb, 240.0f, NodeFlag::Goal); // reliability check
|
||||
}
|
||||
const auto &bomb = graph.getBombOrigin ();
|
||||
const auto &audible = isBombAudible ();
|
||||
|
||||
// take the nearest to bomb nodes instead of goal if close enough
|
||||
else if ((pev->origin - bomb).lengthSq () < cr::square (512.0f)) {
|
||||
int node = graph.getNearest (bomb, 240.0f);
|
||||
if ((pev->origin - bomb).lengthSq () < cr::square (96.0f)) {
|
||||
int node = graph.getNearest (bomb, 420.0f);
|
||||
|
||||
m_bombSearchOverridden = true;
|
||||
|
||||
if (node != kInvalidNodeIndex) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
else if (!audible.empty ()) {
|
||||
m_bombSearchOverridden = true;
|
||||
return graph.getNearest (audible, 240.0f);
|
||||
}
|
||||
else if (goals.empty ()) {
|
||||
return graph.getNearest (bomb, 512.0f); // reliability check
|
||||
}
|
||||
|
||||
|
||||
int goal = 0, count = 0;
|
||||
float lastDistance = kInfiniteDistance;
|
||||
|
|
@ -1851,7 +1848,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
|||
game.testLine (graph[i].origin, graph[posIndex].origin, TraceIgnore::Everything, ent (), &tr);
|
||||
|
||||
// check if line not hit anything
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1909,7 +1906,7 @@ int Bot::findDefendNode (const Vector &origin) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return nodeIndex[rg.int_ (0, static_cast <int> ((index - 1) * 0.5f))];
|
||||
return nodeIndex[rg.int_ (0, (index -1) / 2)];
|
||||
}
|
||||
|
||||
int Bot::findCoverNode (float maxDistance) {
|
||||
|
|
@ -2122,12 +2119,12 @@ bool Bot::advanceMovement () {
|
|||
}
|
||||
|
||||
if (m_baseAgressionLevel < kills && hasPrimaryWeapon ()) {
|
||||
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, game.time () + rg.float_ (m_difficulty * 0.5f, static_cast <float> (m_difficulty)) * 5.0f, true);
|
||||
startTask (Task::Camp, TaskPri::Camp, kInvalidNodeIndex, game.time () + rg.float_ (static_cast <float> (m_difficulty / 2), static_cast <float> (m_difficulty)) * 5.0f, true);
|
||||
startTask (Task::MoveToPosition, TaskPri::MoveToPosition, findDefendNode (graph[nextIndex].origin), game.time () + rg.float_ (3.0f, 10.0f), true);
|
||||
}
|
||||
}
|
||||
else if (bots.canPause () && !isOnLadder () && !isInWater () && !m_currentTravelFlags && isOnFloor ()) {
|
||||
if (static_cast <float> (kills) == m_baseAgressionLevel) {
|
||||
if (cr::fequal (kills, m_baseAgressionLevel)) {
|
||||
m_campButtons |= IN_DUCK;
|
||||
}
|
||||
else if (rg.chance (m_difficulty * 25)) {
|
||||
|
|
@ -2136,22 +2133,18 @@ bool Bot::advanceMovement () {
|
|||
}
|
||||
|
||||
// force terrorist bot to plant bomb
|
||||
if (m_inBombZone && !m_hasProgressBar && m_hasC4) {
|
||||
if (m_inBombZone && !m_hasProgressBar && m_hasC4 && getCurrentTaskId () != Task::PlantBomb) {
|
||||
changeNextGoal ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_pathWalk.hasNext () && m_pathWalk.next () == m_pathWalk.last () && isOccupiedNode (m_pathWalk.last ())) {
|
||||
changeNextGoal ();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_pathWalk.empty ()) {
|
||||
const int destIndex = m_pathWalk.first ();
|
||||
|
||||
// find out about connection flags
|
||||
if (m_currentNodeIndex != kInvalidNodeIndex) {
|
||||
if (destIndex != kInvalidNodeIndex && m_currentNodeIndex != kInvalidNodeIndex) {
|
||||
for (const auto &link : m_path->links) {
|
||||
if (link.index == destIndex) {
|
||||
m_currentTravelFlags = link.flags;
|
||||
|
|
@ -2238,20 +2231,21 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
Vector forward = src + normal * 24.0f;
|
||||
|
||||
const auto &right = Vector (0.0f, pev->angles.y, 0.0f).right ();
|
||||
bool traceResult = false;
|
||||
|
||||
auto checkDoor = [] (TraceResult *tr) {
|
||||
auto checkDoor = [&traceResult] (TraceResult *tr) {
|
||||
if (!game.mapIs (MapFlags::HasDoors)) {
|
||||
return false;
|
||||
}
|
||||
return tr->flFraction < 1.0f && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) != 0;
|
||||
return !traceResult && tr->flFraction < 1.0f && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) != 0;
|
||||
};
|
||||
|
||||
// trace from the bot's eyes straight forward...
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (tr->flFraction < 1.0f) {
|
||||
if (game.mapIs (MapFlags::HasDoors) && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) == 0) {
|
||||
if (!traceResult && game.mapIs (MapFlags::HasDoors) && strncmp ("func_door", tr->pHit->v.classname.chars (), 9) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true; // bot's head will hit something
|
||||
|
|
@ -2262,7 +2256,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
src = getEyesPos () + Vector (0.0f, 0.0f, -16.0f) - right * -16.0f;
|
||||
forward = getEyesPos () + Vector (0.0f, 0.0f, -16.0f) + right * 16.0f + normal * 24.0f;
|
||||
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2274,7 +2268,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
src = getEyesPos () + Vector (0.0f, 0.0f, -16.0f) + right * 16.0f;
|
||||
forward = getEyesPos () + Vector (0.0f, 0.0f, -16.0f) - right * -16.0f + normal * 24.0f;
|
||||
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2286,7 +2280,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
src = pev->origin + Vector (0.0f, 0.0f, -19.0f + 19.0f);
|
||||
forward = src + Vector (0.0f, 0.0f, 10.0f) + normal * 24.0f;
|
||||
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2295,7 +2289,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
src = pev->origin;
|
||||
forward = src + normal * 24.0f;
|
||||
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2308,7 +2302,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
forward = pev->origin + Vector (0.0f, 0.0f, -17.0f) + right * 16.0f + normal * 24.0f;
|
||||
|
||||
// trace from the bot's waist straight forward...
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2319,7 +2313,7 @@ bool Bot::cantMoveForward (const Vector &normal, TraceResult *tr) {
|
|||
src = pev->origin + Vector (0.0f, 0.0f, -24.0f) + right * 16.0f;
|
||||
forward = pev->origin + Vector (0.0f, 0.0f, -24.0f) - right * -16.0f + normal * 24.0f;
|
||||
|
||||
game.testLine (src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
traceResult = game.testLineChannel (TraceChannel::Body, src, forward, TraceIgnore::Monsters, ent (), tr);
|
||||
|
||||
// check if the trace hit something...
|
||||
if (checkDoor (tr)) {
|
||||
|
|
@ -2816,6 +2810,9 @@ void Bot::updateBodyAngles () {
|
|||
pev->angles.y = pev->v_angle.y;
|
||||
|
||||
pev->angles.clampAngles ();
|
||||
|
||||
// calculate frustum plane data here, since lookangles update functions call this last one
|
||||
calculateFrustum ();
|
||||
}
|
||||
|
||||
void Bot::updateLookAngles () {
|
||||
|
|
@ -2830,14 +2827,14 @@ void Bot::updateLookAngles () {
|
|||
direction.clampAngles ();
|
||||
|
||||
// lower skilled bot's have lower aiming
|
||||
if (m_difficulty < 2) {
|
||||
if (m_difficulty < Difficulty::Normal) {
|
||||
updateLookAnglesNewbie (direction, delta);
|
||||
updateBodyAngles ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_difficulty > 3 && (m_aimFlags & AimFlags::Enemy) && (m_wantsToFire || usesSniper ()) && yb_whose_your_daddy.bool_ ()) {
|
||||
if (m_difficulty == Difficulty::Expert && (m_aimFlags & AimFlags::Enemy) && (m_wantsToFire || usesSniper ()) && cv_whose_your_daddy.bool_ ()) {
|
||||
pev->v_angle = direction;
|
||||
updateBodyAngles ();
|
||||
|
||||
|
|
@ -2848,7 +2845,7 @@ void Bot::updateLookAngles () {
|
|||
float stiffness = 200.0f;
|
||||
float damping = 25.0f;
|
||||
|
||||
if ((m_aimFlags & (AimFlags::Enemy | AimFlags::Entity | AimFlags::Grenade)) && m_difficulty > 3) {
|
||||
if ((m_aimFlags & (AimFlags::Enemy | AimFlags::Entity | AimFlags::Grenade)) && m_difficulty > Difficulty::Hard) {
|
||||
stiffness += 100.0f;
|
||||
damping += 5.0f;
|
||||
}
|
||||
|
|
@ -2879,8 +2876,8 @@ void Bot::updateLookAngles () {
|
|||
}
|
||||
|
||||
void Bot::updateLookAnglesNewbie (const Vector &direction, float delta) {
|
||||
Vector spring (13.0f, 13.0f, 0.0f);
|
||||
Vector damperCoefficient (0.22f, 0.22f, 0.0f);
|
||||
Vector spring { 13.0f, 13.0f, 0.0f };
|
||||
Vector damperCoefficient { 0.22f, 0.22f, 0.0f };
|
||||
|
||||
const float offset = cr::clamp (m_difficulty, 1, 4) * 25.0f;
|
||||
|
||||
|
|
@ -2972,7 +2969,7 @@ void Bot::setStrafeSpeed (const Vector &moveDir, float strafeSpeed) {
|
|||
int Bot::getNearestToPlantedBomb () {
|
||||
// this function tries to find planted c4 on the defuse scenario map and returns nearest to it node
|
||||
|
||||
if (m_team != Team::Terrorist || !game.mapIs (MapFlags::Demolition)) {
|
||||
if (!game.mapIs (MapFlags::Demolition)) {
|
||||
return kInvalidNodeIndex; // don't search for bomb if the player is CT, or it's not defusing bomb
|
||||
}
|
||||
int result = kInvalidNodeIndex;
|
||||
|
|
@ -2991,7 +2988,7 @@ int Bot::getNearestToPlantedBomb () {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool Bot::isOccupiedNode (int index) {
|
||||
bool Bot::isOccupiedNode (int index, bool needZeroVelocity) {
|
||||
if (!graph.exists (index)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3005,6 +3002,11 @@ bool Bot::isOccupiedNode (int index) {
|
|||
if ((pev->origin - client.origin).lengthSq () > cr::square (320.0f)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (needZeroVelocity && client.ent->v.velocity.length2d () > 0.0f) {
|
||||
continue;
|
||||
}
|
||||
auto bot = bots[client.ent];
|
||||
|
||||
if (bot == this) {
|
||||
|
|
@ -3020,7 +3022,7 @@ bool Bot::isOccupiedNode (int index) {
|
|||
}
|
||||
float length = (graph[index].origin - client.origin).lengthSq ();
|
||||
|
||||
if (length < cr::clamp (graph[index].radius, cr::square (64.0f), cr::square (120.0f))) {
|
||||
if (length < cr::clamp (graph[index].radius, cr::square (90.0f), cr::square (120.0f))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -3070,6 +3072,11 @@ bool Bot::isReachableNode (int index) {
|
|||
if ((dst - src).lengthSq () >= cr::square (320.0f)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// some one seems to camp at this node
|
||||
if (isOccupiedNode (index, true)) {
|
||||
return true;
|
||||
}
|
||||
float ladderDist = (dst - src).length2d ();
|
||||
|
||||
TraceResult tr {};
|
||||
|
|
@ -1,17 +1,24 @@
|
|||
//
|
||||
// Yet Another POD-Bot, based on PODBot by Markus Klinge ("CountFloyd").
|
||||
// Copyright (c) Yet Another POD-Bot Contributors <yapb@entix.io>.
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This software is licensed under the MIT license.
|
||||
// Additional exceptions apply. For full license details, see LICENSE.txt
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <yapb.h>
|
||||
|
||||
ConVar yb_display_welcome_text ("yb_display_welcome_text", "1", "Enables or disables showing welcome message to host entity on game start.");
|
||||
ConVar yb_enable_query_hook ("yb_enable_query_hook", "1", "Enables or disabled fake server queries response, that shows bots as real players in server browser.");
|
||||
ConVar cv_display_welcome_text ("ub_display_welcome_text", "1", "Enables or disables showing welcome message to host entity on game start.");
|
||||
ConVar cv_enable_query_hook ("ub_enable_query_hook", "1", "Enables or disables fake server queries response, that shows bots as real players in server browser.");
|
||||
|
||||
BotUtils::BotUtils () {
|
||||
BotSupport::BotSupport () {
|
||||
m_needToSendWelcome = false;
|
||||
m_welcomeReceiveTime = 0.0f;
|
||||
|
||||
|
|
@ -64,7 +71,6 @@ BotUtils::BotUtils () {
|
|||
m_noiseCache["weapons/zoo"] = Noise::NeedHandle | Noise::Zoom;
|
||||
m_noiseCache["hostage/hos"] = Noise::NeedHandle | Noise::Hostage;
|
||||
m_noiseCache["debris/bust"] = Noise::NeedHandle | Noise::Broke;
|
||||
m_noiseCache["debris/bust"] = Noise::NeedHandle | Noise::Broke;
|
||||
m_noiseCache["doors/doorm"] = Noise::NeedHandle | Noise::Door;
|
||||
|
||||
// register weapon aliases
|
||||
|
|
@ -104,27 +110,27 @@ BotUtils::BotUtils () {
|
|||
m_clients.resize (kGameMaxPlayers + 1);
|
||||
}
|
||||
|
||||
bool BotUtils::isAlive (edict_t *ent) {
|
||||
bool BotSupport::isAlive (edict_t *ent) {
|
||||
if (game.isNullEntity (ent)) {
|
||||
return false;
|
||||
}
|
||||
return ent->v.deadflag == DEAD_NO && ent->v.health > 0 && ent->v.movetype != MOVETYPE_NOCLIP;
|
||||
}
|
||||
|
||||
bool BotUtils::isVisible (const Vector &origin, edict_t *ent) {
|
||||
bool BotSupport::isVisible (const Vector &origin, edict_t *ent) {
|
||||
if (game.isNullEntity (ent)) {
|
||||
return false;
|
||||
}
|
||||
TraceResult tr {};
|
||||
game.testLine (ent->v.origin + ent->v.view_ofs, origin, TraceIgnore::Everything, ent, &tr);
|
||||
|
||||
if (tr.flFraction != 1.0f) {
|
||||
if (!cr::fequal (tr.flFraction, 1.0f)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BotUtils::traceDecals (entvars_t *pev, TraceResult *trace, int logotypeIndex) {
|
||||
void BotSupport::traceDecals (entvars_t *pev, TraceResult *trace, int logotypeIndex) {
|
||||
// this function draw spraypaint depending on the tracing results.
|
||||
|
||||
auto logo = conf.getRandomLogoName (logotypeIndex);
|
||||
|
|
@ -136,7 +142,7 @@ void BotUtils::traceDecals (entvars_t *pev, TraceResult *trace, int logotypeInde
|
|||
decalIndex = engfuncs.pfnDecalIndex ("{lambda06");
|
||||
}
|
||||
|
||||
if (trace->flFraction == 1.0f) {
|
||||
if (cr::fequal (trace->flFraction, 1.0f)) {
|
||||
return;
|
||||
}
|
||||
if (!game.isNullEntity (trace->pHit)) {
|
||||
|
|
@ -193,7 +199,7 @@ void BotUtils::traceDecals (entvars_t *pev, TraceResult *trace, int logotypeInde
|
|||
}
|
||||
}
|
||||
|
||||
bool BotUtils::isPlayer (edict_t *ent) {
|
||||
bool BotSupport::isPlayer (edict_t *ent) {
|
||||
if (game.isNullEntity (ent)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -208,7 +214,7 @@ bool BotUtils::isPlayer (edict_t *ent) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BotUtils::isPlayerVIP (edict_t *ent) {
|
||||
bool BotSupport::isPlayerVIP (edict_t *ent) {
|
||||
if (!game.mapIs (MapFlags::Assassination)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -219,28 +225,26 @@ bool BotUtils::isPlayerVIP (edict_t *ent) {
|
|||
return *(engfuncs.pfnInfoKeyValue (engfuncs.pfnGetInfoKeyBuffer (ent), "model")) == 'v';
|
||||
}
|
||||
|
||||
bool BotUtils::isFakeClient (edict_t *ent) {
|
||||
bool BotSupport::isFakeClient (edict_t *ent) {
|
||||
if (bots[ent] != nullptr || (!game.isNullEntity (ent) && (ent->v.flags & FL_FAKECLIENT))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BotUtils::openConfig (const char *fileName, const char *errorIfNotExists, MemFile *outFile, bool languageDependant /*= false*/) {
|
||||
bool BotSupport::openConfig (const char *fileName, const char *errorIfNotExists, MemFile *outFile, bool languageDependant /*= false*/) {
|
||||
if (*outFile) {
|
||||
outFile->close ();
|
||||
}
|
||||
|
||||
// save config dir
|
||||
const char *configDir = "addons/yapb/conf";
|
||||
auto configDir = strings.format ("addons/%s/conf", product.folder);
|
||||
|
||||
if (languageDependant) {
|
||||
extern ConVar yb_language;
|
||||
|
||||
if (strcmp (fileName, "lang.cfg") == 0 && strcmp (yb_language.str (), "en") == 0) {
|
||||
if (strcmp (fileName, "lang.cfg") == 0 && strcmp (cv_language.str (), "en") == 0) {
|
||||
return false;
|
||||
}
|
||||
auto langConfig = strings.format ("%s/lang/%s_%s", configDir, yb_language.str (), fileName);
|
||||
auto langConfig = strings.format ("%s/lang/%s_%s", configDir, cv_language.str (), fileName);
|
||||
|
||||
// check is file is exists for this language
|
||||
if (!outFile->open (langConfig)) {
|
||||
|
|
@ -258,10 +262,10 @@ bool BotUtils::openConfig (const char *fileName, const char *errorIfNotExists, M
|
|||
return true;
|
||||
}
|
||||
|
||||
void BotUtils::checkWelcome () {
|
||||
void BotSupport::checkWelcome () {
|
||||
// the purpose of this function, is to send quick welcome message, to the listenserver entity.
|
||||
|
||||
if (game.isDedicated () || !yb_display_welcome_text.bool_ () || !m_needToSendWelcome) {
|
||||
if (game.isDedicated () || !cv_display_welcome_text.bool_ () || !m_needToSendWelcome) {
|
||||
return;
|
||||
}
|
||||
m_welcomeReceiveTime = 0.0f;
|
||||
|
|
@ -274,15 +278,14 @@ void BotUtils::checkWelcome () {
|
|||
m_welcomeReceiveTime = game.time () + 4.0f; // receive welcome message in four seconds after game has commencing
|
||||
}
|
||||
|
||||
|
||||
if (m_welcomeReceiveTime > 0.0f && needToSendMsg) {
|
||||
if (!game.is (GameFlags::Mobility | GameFlags::Xash3D)) {
|
||||
game.serverCommand ("speak \"%s\"", m_sentences.random ().chars ());
|
||||
game.serverCommand ("speak \"%s\"", m_sentences.random ());
|
||||
}
|
||||
|
||||
MessageWriter (MSG_ONE, msgs.id (NetMsg::TextMsg), nullptr, receiveEntity)
|
||||
.writeByte (HUD_PRINTTALK)
|
||||
.writeString (strings.format ("----- %s v%s (Build: %u), {%s}, (c) %s, by %s (%s)-----", PRODUCT_SHORT_NAME, PRODUCT_VERSION, buildNumber (), PRODUCT_DATE, PRODUCT_END_YEAR, PRODUCT_AUTHOR, PRODUCT_URL));
|
||||
.writeString (strings.format ("----- %s v%s (Build: %s), {%s}, (c) %s, by %s (%s)-----", product.name, product.version, product.build.count, product.date, product.year, product.author, product.url));
|
||||
|
||||
MessageWriter (MSG_ONE, SVC_TEMPENTITY, nullptr, receiveEntity)
|
||||
.writeByte (TE_TEXTMESSAGE)
|
||||
|
|
@ -302,14 +305,14 @@ void BotUtils::checkWelcome () {
|
|||
.writeShort (MessageWriter::fu16 (2.0f, 8.0f))
|
||||
.writeShort (MessageWriter::fu16 (6.0f, 8.0f))
|
||||
.writeShort (MessageWriter::fu16 (0.1f, 8.0f))
|
||||
.writeString (strings.format ("\nServer is running %s v%s (Build: %u)\nDeveloped by %s\n\n%s", PRODUCT_SHORT_NAME, PRODUCT_VERSION, buildNumber (), PRODUCT_AUTHOR, graph.getAuthor ()));
|
||||
.writeString (strings.format ("\nHello! You are playing with %s v%s (Build: %s)\nDevised by %s\n\n%s", product.name, product.version, product.build.count, product.author, graph.getAuthor ()));
|
||||
|
||||
m_welcomeReceiveTime = 0.0f;
|
||||
m_needToSendWelcome = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BotUtils::findNearestPlayer (void **pvHolder, edict_t *to, float searchDistance, bool sameTeam, bool needBot, bool needAlive, bool needDrawn, bool needBotWithC4) {
|
||||
bool BotSupport::findNearestPlayer (void **pvHolder, edict_t *to, float searchDistance, bool sameTeam, bool needBot, bool needAlive, bool needDrawn, bool needBotWithC4) {
|
||||
// this function finds nearest to to, player with set of parameters, like his
|
||||
// team, live status, search distance etc. if needBot is true, then pvHolder, will
|
||||
// be filled with bot pointer, else with edict pointer(!).
|
||||
|
|
@ -349,7 +352,7 @@ bool BotUtils::findNearestPlayer (void **pvHolder, edict_t *to, float searchDist
|
|||
return true;
|
||||
}
|
||||
|
||||
void BotUtils::listenNoise (edict_t *ent, const String &sample, float volume) {
|
||||
void BotSupport::listenNoise (edict_t *ent, StringRef sample, float volume) {
|
||||
// this function called by the sound hooking code (in emit_sound) enters the played sound into the array associated with the entity
|
||||
|
||||
if (game.isNullEntity (ent) || sample.empty ()) {
|
||||
|
|
@ -438,7 +441,7 @@ void BotUtils::listenNoise (edict_t *ent, const String &sample, float volume) {
|
|||
}
|
||||
}
|
||||
|
||||
void BotUtils::simulateNoise (int playerIndex) {
|
||||
void BotSupport::simulateNoise (int playerIndex) {
|
||||
// this function tries to simulate playing of sounds to let the bots hear sounds which aren't
|
||||
// captured through server sound hooking
|
||||
|
||||
|
|
@ -506,7 +509,7 @@ void BotUtils::simulateNoise (int playerIndex) {
|
|||
}
|
||||
}
|
||||
|
||||
void BotUtils::updateClients () {
|
||||
void BotSupport::updateClients () {
|
||||
|
||||
// record some stats of all players on the server
|
||||
for (int i = 0; i < game.maxClients (); ++i) {
|
||||
|
|
@ -536,7 +539,7 @@ void BotUtils::updateClients () {
|
|||
}
|
||||
}
|
||||
|
||||
int BotUtils::getPingBitmask (edict_t *ent, int loss, int ping) {
|
||||
int BotSupport::getPingBitmask (edict_t *ent, int loss, int ping) {
|
||||
// this function generats bitmask for SVC_PINGS engine message. See SV_EmitPings from engine for details
|
||||
|
||||
const auto emit = [] (int s0, int s1, int s2) {
|
||||
|
|
@ -545,8 +548,8 @@ int BotUtils::getPingBitmask (edict_t *ent, int loss, int ping) {
|
|||
return emit (loss, 7, 18) | emit (ping, 12, 6) | emit (game.indexOfPlayer (ent), 5, 1) | 1;
|
||||
}
|
||||
|
||||
void BotUtils::calculatePings () {
|
||||
if (!game.is (GameFlags::HasFakePings) || yb_show_latency.int_ () != 2) {
|
||||
void BotSupport::calculatePings () {
|
||||
if (!game.is (GameFlags::HasFakePings) || cv_show_latency.int_ () != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -601,7 +604,7 @@ void BotUtils::calculatePings () {
|
|||
}
|
||||
}
|
||||
|
||||
void BotUtils::sendPings (edict_t *to) {
|
||||
void BotSupport::sendPings (edict_t *to) {
|
||||
MessageWriter msg;
|
||||
|
||||
// missing from sdk
|
||||
|
|
@ -628,9 +631,9 @@ void BotUtils::sendPings (edict_t *to) {
|
|||
return;
|
||||
}
|
||||
|
||||
void BotUtils::installSendTo () {
|
||||
void BotSupport::installSendTo () {
|
||||
// if previously requested to disable?
|
||||
if (!yb_enable_query_hook.bool_ ()) {
|
||||
if (!cv_enable_query_hook.bool_ ()) {
|
||||
if (m_sendToHook.enabled ()) {
|
||||
disableSendTo ();
|
||||
}
|
||||
|
|
@ -644,11 +647,23 @@ void BotUtils::installSendTo () {
|
|||
|
||||
// enable only on modern games
|
||||
if (game.is (GameFlags::Modern) && (plat.linux || plat.win32) && !plat.arm && !m_sendToHook.enabled ()) {
|
||||
m_sendToHook.patch (reinterpret_cast <void *> (&sendto), reinterpret_cast <void *> (&BotUtils::sendTo));
|
||||
m_sendToHook.patch (reinterpret_cast <void *> (&sendto), reinterpret_cast <void *> (&BotSupport::sendTo));
|
||||
}
|
||||
}
|
||||
|
||||
int32 BotUtils::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) {
|
||||
bool BotSupport::isObjectInsidePlane (FrustumPlane &plane, const Vector ¢er, float height, float radius) {
|
||||
auto isPointInsidePlane = [&](const Vector &point) -> bool {
|
||||
return plane.result + (plane.normal | point) >= 0.0f;
|
||||
};
|
||||
|
||||
const Vector &test = plane.normal.get2d ();
|
||||
const Vector &top = center + Vector (0.0f, 0.0f, height * 0.5f) + test * radius;
|
||||
const Vector &bottom = center - Vector (0.0f, 0.0f, height * 0.5f) + test * radius;
|
||||
|
||||
return isPointInsidePlane (top) || isPointInsidePlane (bottom);
|
||||
}
|
||||
|
||||
int32 BotSupport::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) {
|
||||
const auto send = [&] (const Twin <const uint8 *, size_t> &msg) -> int32 {
|
||||
return Socket::sendto (socket, msg.first, msg.second, flags, dest, destLength);
|
||||
};
|
||||
|
|
@ -663,14 +678,12 @@ int32 BotUtils::sendTo (int socket, const void *message, size_t length, int flag
|
|||
auto count = buffer.read <uint8> ();
|
||||
|
||||
for (uint8 i = 0; i < count; ++i) {
|
||||
buffer.read <uint8> (); // number
|
||||
buffer.write <uint8> (i); // override number
|
||||
|
||||
buffer.skip <uint8> (); // number
|
||||
buffer.skipString (); // name
|
||||
buffer.skip <int32> (); // score
|
||||
|
||||
buffer.read <float> (); // override connection time
|
||||
buffer.write <float> (bots.getConnectionTime (i));
|
||||
auto ctime = buffer.read <float> (); // override connection time
|
||||
buffer.write <float> (bots.getConnectTime (i, ctime));
|
||||
}
|
||||
return send (buffer.data ());
|
||||
}
|
||||
|
|
@ -702,50 +715,8 @@ int32 BotUtils::sendTo (int socket, const void *message, size_t length, int flag
|
|||
return send ({ packet, length });
|
||||
}
|
||||
|
||||
int BotUtils::buildNumber () {
|
||||
// this function generates build number from the compiler date macros
|
||||
|
||||
static int buildNumber = 0;
|
||||
|
||||
if (buildNumber != 0) {
|
||||
return buildNumber;
|
||||
}
|
||||
// get compiling date using compiler macros
|
||||
const char *date = __DATE__;
|
||||
|
||||
// array of the month names
|
||||
const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
// array of the month days
|
||||
uint8 monthDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
int day = 0; // day of the year
|
||||
int year = 0; // year
|
||||
int i = 0;
|
||||
|
||||
// go through all months, and calculate, days since year start
|
||||
for (i = 0; i < 11; ++i) {
|
||||
if (strncmp (&date[0], months[i], 3) == 0) {
|
||||
break; // found current month break
|
||||
}
|
||||
day += monthDays[i]; // add month days
|
||||
}
|
||||
day += atoi (&date[4]) - 1; // finally calculate day
|
||||
year = atoi (&date[7]) - 2000; // get years since year 2000
|
||||
|
||||
buildNumber = day + static_cast <int> ((year - 1) * 365.25);
|
||||
|
||||
// if the year is a leap year?
|
||||
if ((year % 4) == 0 && i > 1) {
|
||||
buildNumber += 1; // add one year more
|
||||
}
|
||||
buildNumber -= 1114;
|
||||
|
||||
return buildNumber;
|
||||
}
|
||||
|
||||
const String &BotUtils::weaponIdToAlias (const int32 id) {
|
||||
static const String &none = "none";
|
||||
StringRef BotSupport::weaponIdToAlias (int32 id) {
|
||||
StringRef none = "none";
|
||||
|
||||
if (m_weaponAlias.exists (id)) {
|
||||
return m_weaponAlias[id];
|
||||
47
vc/yapb.rc
Normal file
47
vc/yapb.rc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// YaPB - Counter-Strike Bot based on PODBot by Markus Klinge.
|
||||
// Copyright © 2004-2020 YaPB Development Team <team@yapb.ru>.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
|
||||
#include <winver.h>
|
||||
|
||||
#ifdef VERSION_GENERATED
|
||||
# define VERSION_HEADER <version.build.h>
|
||||
#else
|
||||
# define VERSION_HEADER "../inc/version.h"
|
||||
#endif
|
||||
|
||||
#include VERSION_HEADER
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION MODULE_BOT_VERSION_FILE
|
||||
PRODUCTVERSION MODULE_BOT_VERSION_FILE
|
||||
FILEOS 0x40004
|
||||
FILETYPE 0x2 {
|
||||
BLOCK "StringFileInfo" {
|
||||
BLOCK "040904E4" {
|
||||
VALUE "CompanyName", "YaPB Development Team" "\0"
|
||||
VALUE "FileDescription", "YaPB v" MODULE_BOT_VERSION "." MODULE_BUILD_COUNT " - The Counter-Strike Bot" "\0"
|
||||
VALUE "LegalCopyright", "Copyright \251 2020 YaPB Development Team" "\0"
|
||||
VALUE "OriginalFilename", "yapb.dll" "\0"
|
||||
VALUE "ProductName", "YaPB" "\0"
|
||||
VALUE "InternalName", "YaPB DLL" "\0"
|
||||
VALUE "FileVersion", MODULE_BOT_VERSION "." MODULE_BUILD_COUNT "\0"
|
||||
VALUE "ProductVersion", MODULE_BOT_VERSION "." MODULE_BUILD_COUNT "\0"
|
||||
VALUE "SpecialBuild", MODULE_BOT_BUILD_ID "\0"
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo" {
|
||||
VALUE "Translation", 0x400, 1200
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project DefaultTargets="Build" ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
|
|
@ -11,65 +11,69 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\config.h" />
|
||||
<ClInclude Include="..\include\control.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-alloc.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-array.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-basic.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-binheap.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-color.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-complete.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-dict.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-files.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-hook.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-http.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-lambda.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-library.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-logger.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-math.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-movable.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-platform.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-random.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-string.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-twin.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-ulz.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-uniqueptr.h" />
|
||||
<ClInclude Include="..\include\crlib\cr-vector.h" />
|
||||
<ClInclude Include="..\include\engine\model.h" />
|
||||
<ClInclude Include="..\include\graph.h" />
|
||||
<ClInclude Include="..\include\manager.h" />
|
||||
<ClInclude Include="..\include\message.h" />
|
||||
<ClInclude Include="..\include\utils.h" />
|
||||
<ClInclude Include="..\include\yapb.h" />
|
||||
<ClInclude Include="..\include\engine.h" />
|
||||
<ClInclude Include="..\include\engine\const.h" />
|
||||
<ClInclude Include="..\include\engine\eiface.h" />
|
||||
<ClInclude Include="..\include\engine\extdll.h" />
|
||||
<ClInclude Include="..\include\engine\meta_api.h" />
|
||||
<ClInclude Include="..\include\engine\progdefs.h" />
|
||||
<ClInclude Include="..\include\engine\util.h" />
|
||||
<ClInclude Include="..\include\resource.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-alloc.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-array.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-basic.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-binheap.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-color.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-complete.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-dict.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-files.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-hook.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-http.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-lambda.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-library.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-logger.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-math.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-movable.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-platform.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-random.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-string.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-twin.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-ulz.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-uniqueptr.h" />
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-vector.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\const.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\eiface.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\extdll.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\metamod.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\meta_api.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\model.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\progdefs.h" />
|
||||
<ClInclude Include="..\ext\sdk\sdk\util.h" />
|
||||
<ClInclude Include="..\inc\config.h" />
|
||||
<ClInclude Include="..\inc\control.h" />
|
||||
<ClInclude Include="..\inc\engine.h" />
|
||||
<ClInclude Include="..\inc\graph.h" />
|
||||
<ClInclude Include="..\inc\manager.h" />
|
||||
<ClInclude Include="..\inc\message.h" />
|
||||
<ClInclude Include="..\inc\product.h" />
|
||||
<ClInclude Include="..\inc\support.h" />
|
||||
<ClInclude Include="..\inc\yapb.h" />
|
||||
<ClInclude Include="..\inc\version.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\source\android.cpp" />
|
||||
<ClCompile Include="..\source\basecode.cpp" />
|
||||
<ClCompile Include="..\source\combat.cpp" />
|
||||
<ClCompile Include="..\source\engine.cpp" />
|
||||
<ClCompile Include="..\source\manager.cpp" />
|
||||
<ClCompile Include="..\source\chatlib.cpp" />
|
||||
<ClCompile Include="..\source\control.cpp" />
|
||||
<ClCompile Include="..\source\linkage.cpp" />
|
||||
<ClCompile Include="..\source\message.cpp" />
|
||||
<ClCompile Include="..\source\navigate.cpp" />
|
||||
<ClCompile Include="..\source\support.cpp" />
|
||||
<ClCompile Include="..\source\graph.cpp" />
|
||||
<ClCompile Include="..\src\android.cpp" />
|
||||
<ClCompile Include="..\src\botlib.cpp" />
|
||||
<ClCompile Include="..\src\chatlib.cpp" />
|
||||
<ClCompile Include="..\src\combat.cpp" />
|
||||
<ClCompile Include="..\src\control.cpp" />
|
||||
<ClCompile Include="..\src\engine.cpp" />
|
||||
<ClCompile Include="..\src\graph.cpp" />
|
||||
<ClCompile Include="..\src\linkage.cpp" />
|
||||
<ClCompile Include="..\src\manager.cpp" />
|
||||
<ClCompile Include="..\src\message.cpp" />
|
||||
<ClCompile Include="..\src\navigate.cpp" />
|
||||
<ClCompile Include="..\src\support.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="yapb.rc" />
|
||||
<ResourceCompile Include="yapb.rc">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\source\Android.mk" />
|
||||
<None Include="makefile" />
|
||||
<None Include="..\inc\version.h.in" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C232645A-3B99-48F4-A1F3-F20CF0A9568B}</ProjectGuid>
|
||||
|
|
@ -88,6 +92,7 @@
|
|||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<EnableASAN>false</EnableASAN>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
|
@ -131,16 +136,16 @@
|
|||
<MkTypLibCompatible>true</MkTypLibCompatible>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<TargetEnvironment>Win32</TargetEnvironment>
|
||||
<TypeLibraryName>.\debug/yapb.tlb</TypeLibraryName>
|
||||
<TypeLibraryName>./debug/yapb.tlb</TypeLibraryName>
|
||||
<HeaderFileName />
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\vc;..\inc;..\ext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader />
|
||||
<PrecompiledHeaderFile>core.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile>yapb.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>.\debug\inf\yapb.pch</PrecompiledHeaderOutputFile>
|
||||
<ExpandAttributedSource>false</ExpandAttributedSource>
|
||||
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
|
||||
|
|
@ -153,12 +158,12 @@
|
|||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<FloatingPointModel>Strict</FloatingPointModel>
|
||||
<StringPooling>true</StringPooling>
|
||||
<StringPooling>false</StringPooling>
|
||||
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DisableLanguageExtensions>false</DisableLanguageExtensions>
|
||||
<LanguageStandard>Default</LanguageStandard>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
|
@ -170,7 +175,7 @@
|
|||
<Link>
|
||||
<OutputFile>.\debug\yapb.dll</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>.\debug\inf\yapb.pdb</ProgramDatabaseFile>
|
||||
<GenerateMapFile>true</GenerateMapFile>
|
||||
<MapFileName>.\debug\inf\yapb.map</MapFileName>
|
||||
|
|
@ -209,7 +214,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\vc;..\inc;..\ext;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>NDEBUG;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
|
|
@ -222,7 +227,7 @@
|
|||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DebugInformationFormat>None</DebugInformationFormat>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<InterproceduralOptimization>SingleFile</InterproceduralOptimization>
|
||||
<InterproceduralOptimization>MultiFile</InterproceduralOptimization>
|
||||
<FlushDenormalResultsToZero>true</FlushDenormalResultsToZero>
|
||||
<Parallelization>false</Parallelization>
|
||||
<FloatingPointModel>Fast</FloatingPointModel>
|
||||
|
|
@ -254,15 +259,13 @@
|
|||
<OutputFile>.\release\yapb.dll</OutputFile>
|
||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||
<DelayLoadDLLs>user32.dll;ws2_32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<GenerateMapFile>false</GenerateMapFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<SetChecksum>false</SetChecksum>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention />
|
||||
<TurnOffAssemblyGeneration>true</TurnOffAssemblyGeneration>
|
||||
<ImportLibrary>.\release\inf\yapb.lib</ImportLibrary>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
<MinimumRequiredVersion />
|
||||
|
|
@ -270,7 +273,7 @@
|
|||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ImageHasSafeExceptionHandlers>
|
||||
</ImageHasSafeExceptionHandlers>
|
||||
<LinkTimeCodeGeneration>UseFastLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
|
||||
<FullProgramDatabaseFile>true</FullProgramDatabaseFile>
|
||||
<ShowProgress>NotSet</ShowProgress>
|
||||
</Link>
|
||||
193
vc/yapb.vcxproj.filters
Normal file
193
vc/yapb.vcxproj.filters
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="src">
|
||||
<UniqueIdentifier>{55dff0ff-c17f-4ef8-9949-652a53eacda0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="inc">
|
||||
<UniqueIdentifier>{0ad17b3f-102e-4f74-b1aa-dd492e79dca2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="inc\ext">
|
||||
<UniqueIdentifier>{11ec3b8b-d4e5-4f43-964c-b84980a6d0e1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="inc\ext\crlib">
|
||||
<UniqueIdentifier>{bec0fb46-08b4-4bfa-900c-d279a933ff77}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="inc\ext\sdk">
|
||||
<UniqueIdentifier>{f6a0fc04-bdf5-479b-8e5a-85eae698541e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="res">
|
||||
<UniqueIdentifier>{5e73b918-f42b-4df9-bbe9-918289e44ad2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\inc\config.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\control.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\engine.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\graph.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\manager.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\message.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\yapb.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-alloc.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-array.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-basic.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-binheap.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-color.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-complete.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-dict.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-files.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-hook.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-http.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-lambda.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-library.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-logger.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-math.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-movable.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-platform.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-random.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-string.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-twin.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-ulz.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-uniqueptr.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\crlib\crlib\cr-vector.h">
|
||||
<Filter>inc\ext\crlib</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\const.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\eiface.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\extdll.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\meta_api.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\metamod.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\model.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\progdefs.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\ext\sdk\sdk\util.h">
|
||||
<Filter>inc\ext\sdk</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\product.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\support.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\inc\version.h">
|
||||
<Filter>inc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\android.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\botlib.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\chatlib.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\combat.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\control.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\engine.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\graph.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\linkage.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\manager.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\message.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\navigate.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\support.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="yapb.rc">
|
||||
<Filter>res</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\inc\version.h.in">
|
||||
<Filter>inc</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
Add table
Add a link
Reference in a new issue