好痛苦啊 紫钻什么时候升级级...赐我力量,...

[1.30] 保持的力量:接口开发最佳实践
时间: 22:49:39
&&&& 阅读:227
&&&& 评论:
&&&& 收藏:0
标签:神啊,求你赐给我平静的心,去接受我无法改变的事;赐给我勇气,去做我能改变的事;赐给我智慧,去分辨两者的不同。 --平静之祷 &
1.30.1 论保持的力量
追到一个心仪的女生不难,难于如何保持和培养一份真挚的感情;获得一时的财富也不难,难于如何长久保持收益;创业的公司很容易博得一时媒体的关注以及某次天使的投资,但难于如何排除各种障碍、充分利用各方资源发展成中企业及至上市公司。
同样,提供一时的接口很容易,但当我们需要不断为接口提供升级,以及当我们维护提供一整套接口时,面临的困难和问题会越来越大。所以,这是一场持久的战役。需要我们用稳重的心态、专业的能力在背后持久支撑、推动。
值得庆幸的是,这些都是问题而不是限制,都是可以被解决的。以下是结合 @郭了个浩浩 同学提供的apigee.web_api.pdf文档,以及我们多年来的项目实际开发经验为新手提供的一些建议,对老同学相信也会有所帮助。每个建议通常会包括三部分: 现在主流的做法、PhalApi的做法以及项目的选取。
1.30.2 最佳实践建议
为了大家查阅和翻看,这里先罗列本章的全部建议:
(1)接口风格和协议的选择 - HTTP
(2)接口域名 - 使用api单独域名
(3)异常处理 - 200/400/500三大接口结果状态码
(4)对外的命名规则 - 使用小写加下划线
(5)对内的命名规则 - 使用驼峰法和遵循PEAR命名
(6)安全与验证 - 使用接口签名和token登录态双重机制
(7)返回结果格式 - JSON
(8)URL规则与路由映射 - 统一service接口服务,可一个文件一个接口
(9)SDK包 - 给客户端自由的调用空间和自由
(10)接口文档 - 使用markdown快速编写
(11)测试驱动开发 - 坚持单元测试
1.30.3 建议细说
(1)接口风格和协议的选择 - HTTP
目前,后台接口开发可以用RESTFull风格,也可以用Web Service;可以用SOAP协议、RPC协议,也可以用HTTP协议;可以用短链接,也可以使用长链接。如果我们希望继续进行划分,还可以分为同步或 异步、单个或批量、是否有SDK包、内部接口还是开放接口平台等。
主流的做法
现在看来,大部分大型的企业以及大多数的小公司使用的都是HTTP协议下的接口开发,部分使用RESTFull,但Web Service较少。如:
,使用REST风格,
,采用Web Service、SOAP、REST等多种风格和协议提供服务,
PhalApi的做法
我们选取了HTTP的协议,在于其无论是客户端接入、开发调试,还是部署构建上都很容易实现,而且也符合主流,因为大家都比较熟悉。这一点是非常重要的:因为简单,后台接口开发的同学才会更容易上手;因为容易,客户端接入才会更加无压力而不用担心处处受挫。
项目的选取
根据项目不同的项目背景和需求,可以选择你合适的风格或者协议。但是即使出于安全、性能或者其他技术或非技术的原因而不采用HTTP协议的情况下, 你也可以在PhalApi原有的接口开发实现时,轻松扩展你需要的协议。如使用SOAP,PHPRpc或者swoole下的TCP协议。其中,部分协议已 有扩展类库提供支持。
(2)接口域名 - 使用api单独域名
首先,有一点是可以肯定的。接口系统应该有自己单独的域名,而不应该附属于网站或者管理后台。
主流的做法
显然,主流做法也是这样做的。如:
优酷开放平台:
微信公众号:
新浪微博:
项目的选取
如果可以,尽量让接口系统使用独立的域名,并且使用api作为一级域名。如:
//你的网站为:
//则对应的接口为:
(3)异常处理 - 200/400/500三大接口结果状态码
对于接口的异常处理,在使用HTTP协议下,可以通过HTTP本身的响应状态码来进行区分。 在非HTTP协议并有SDK包的情况下,异常的处理手段则会更为多样。
主流的做法
优酷接口采用了HTTP响应状态码加结果返回的形式,如:
Request&URL:/v2/videos/show_basic.json
Request&Method:GET
Status&Code:400&Bad&Request
{"error":{"code":1004,"type":"SystemException","description":"Client&id&null"}}
新浪微博也一样:
Request&URL:/2/statuses/mentions/ids.json
Request&Method:GET
Status&Code:403&Forbidden
{"error":"auth&by&Null&spi!","error_code":21301,"request":"/2/statuses/mentions/ids.json"}
微信接口则采用了统一200的形式,如:
Request&URL:https://api./cgi-bin/token?grant_type=client_credential&appid=
Request&Method:GET
Status&Code:200&OK
{"errcode":41002,"errmsg":"appid&missing"}
PhalApi的做法
为了与HTTP保持一致性,同时降低不必要的复杂性,我们采用了200/400/500三大接口结果状态码。
注意,这里所说的三大状态码,是指接口返回结果中的状态码,而不是HTTP的响应状态。也就是说接口全部的结果返回都应该是200,除非接口服务有内部未捕获的异常,即:
Status&Code:200&OK
返回结果状态码刚是以下几种:
//正常返回
&&&&"ret":&200,
&&&&"data":&{
&&&&&&&&//...
&&&&"msg":&""
//客户端非法请求
&&&&"ret":&400,
&&&&"data":&[],
&&&&"msg":&"非法请求:接口服务Default.Test不存在"
//服务端内部错误
&&&&"ret":&500,
&&&&"data":&[],
&&&&"msg":&"服务器运行错误:&can&not&connect&to&database&db_demo"
####项目的选取
你可以根据你的需要,扩展400和500这两系列的错误,如401表示登录失败等。&&
此外,在data里面,你也可以添加一个code来表示业务级的操作码,以及客户端根据不同的业务场景做出不同和反应、交互或引导提示。
(4)对外的命名规则 - 使用小写加下划线
对外的命名,是指外部看得到的命名,如接口参数的名字,接口返回的结果节点名字,以及数据库的表名、字段名。
主流的做法
新浪微博采用了小写加下划线的做法,如:
https://c./2/friendships/followers/trend_count.json
//请求参数
access_token
//返回结果
&&&&"uid":&10438,
&&&&"result":&[&&&&&&&&&&&&
&&&&&&&&&&&&"days":&"",
&&&&&&&&&&&&"follower_count_online":"15",&&//粉丝数&
&&&&&&&&&&&&"active_follower":"14",&//活跃粉丝数
&&&&&&&&&&&&"loyal_follower":"0"&&&//互动粉丝数&&&&&&&&&&&&
&&&&&&&&},
&&&&&&&&....
Amazon采用了首字母大写且无下划线的做法,如:
//Responses
HTTP/1.1&200&OK
Date:&Wed,&25&Nov&:00&GMT
Connection:&close
Server:&AmazonS3
&?xml&version="1.0"&encoding="UTF-8"?&
&BucketLoggingStatus&xmlns="http://doc./"&
&&&LoggingEnabled&
&&&&&TargetBucket&mybucketlogs&/TargetBucket&
&&&&&TargetPrefix&mybucket-access_log-/&/TargetPrefix&
&&&&&TargetGrants&
&&&&&&&Grant&
&&&&&&&&&Grantee&xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
&&&&&&&&&&xsi:type="AmazonCustomerByEmail"&
&&&&&&&&&&&EmailAddress&&/EmailAddress&
&&&&&&&&&/Grantee&
&&&&&&&&&Permission&READ&/Permission&
&&&&&&&/Grant&
&&&&&/TargetGrants&
&&&/LoggingEnabled&
&/BucketLoggingStatus&
PhalApi的做法
我们提倡使用全部小写加下划线的命名,因为这样更符合客户端的使用,如: 接口参数:
&user_id=888
&user_id=888
返回字段:
"device_type":&"cube",
"deviceType":&"cube",
数据库字段:
`user_id`&bigint(20)&DEFAULT&‘0‘&COMMENT&‘创建者的用户ID‘,
`userId`&bigint(20)&DEFAULT&‘0‘&COMMENT&‘创建者的用户ID‘,
项目的选取
不管是使用全部小写,还是全部大写,项目都应该保持一致的命名风格,而不是混合凌乱的风格。
(5)对内的命名规则 - 使用驼峰法和遵循PEAR命名
与对外命名对应的则是对内的命名规则,这里又回归到了老生常谈的PHP代码风格。这里不作过多的说明,只是稍作提及。
PhalApi的做法
我们建议使用PEAR包的命名风格,和驼峰法,如下为一个接口示例:
$&vim&./Api/Default.php&
&*&默认接口服务类
&*&@author:&dogstar&&&&
class&Api_Default&extends&PhalApi_Api&{
&&&&public&function&getRules()&{
&&&&&&&&return&array(
&&&&&&&&&&&&‘index‘&=&&array(
&&&&&&&&&&&&&&&&‘username‘&&=&&array(‘name‘&=&&‘username‘,&‘default‘&=&&‘PHPer‘,&),
&&&&&&&&&&&&),
&&&&&&&&);
&&&&public&function&index()&{
&&&&&&&&return&array(
&&&&&&&&&&&&‘title‘&=&&‘Default&Api‘,
&&&&&&&&&&&&‘content‘&=&&T(‘Hello&{name},&Welcome&to&use&PhalApi!‘,&array(‘name‘&=&&$this-&username)),
&&&&&&&&&&&&‘version‘&=&&PHALAPI_VERSION,
&&&&&&&&&&&&‘time‘&=&&$_SERVER[‘REQUEST_TIME‘],
&&&&&&&&);
项目的选取
你可以选择你喜欢的风格,但团队应该保持一致。
即便你不喜欢PhalApi约定的PEAR命名,你也可以自行实现内部的类加载机制。当有多个项目或者多个模块并存时,可以添加模块名前缀来作区分,如:
├──&Demo
│&&&└──&Api
│&&&&&&&└──&DUser.php
├──&MyApp
│&&&└──&Api
│&&&&&&&└──&MUser.php
└──&Task
&&&&└──&Api
&&&&&&&&└──&TUser.php
$&head&*/*/*
==&&Demo/Api/DUser.php&&==
class&Api_DUser&extends&PhalApi_Api&{
==&&MyApp/Api/MUser.php&&==
class&Api_MUser&extends&PhalApi_Api&{
==&&Task/Api/TUser.php&&==
class&Api_TUser&extends&PhalApi_Api&{
其它的Domain层和Model层等也类似,这样可以避免类名冲突,或者IDE开发环境下的混淆。
(6)安全与验证 - 使用接口签名和token登录态双重机制
既然采用HTTP协议,那么安全方面就需要接口自身进行保证。
所幸,现在可用的加密手段有多种选择。对于接口签名,我们可以使用非对称的验签方式,如md5;也可以用对称的方式,如RSA。最后,为每一个接入的客户端分配app_key和app_secrect即可。
当然,更好的安全是接口系统再提供登录态的验证,即通常所说的token。 这两者的相合,会为接口增加更好的安全保障。
主流的做法
七牛云存储,采用Access Key/Secret Key,并且在需要时添加相应的凭证
微信公众号,采用由AppID(应用ID)和AppSecret(应用密钥)生成的ACCESS_TOKEN
优酷开放平台,采用应用Key client_id
PhalApi的做法
我们不提供具体的接口签名方案,是因为把这种决策移交给项目应用本身进行定制。而定制也是非常简单的,只需要简单的两步即可:
1、实现过滤器接口 PhalApi_Filter::check();
2、注册过滤器服务 DI()-&filter;
对于token,虽然框架没有提供内置的实现,但可以从PhalApi的扩展类库寻找这种支持,这一点已经User扩展类库支持。
项目的选取
正如PhalApi提供的自由空间,项目可以自行实现接口签名,和根据需要是否采用User扩展类库,或者自行实现token的处理。
(7)返回结果格式 - JSON
在 一节中,已经对JSON的返回格式作了说明,这里不再赘述,也只是稍作提及。
主流的做法
目前采用了JSON的格式返回的有:
优酷开放平台
腾讯开放平台
采用了XML格式返回的有:
PhalApi的做法
我们默认采了JSON的格式返回。
项目的选取
项目可以轻松扩展成其他格式的返回。
(8)URL规则与路由映射 - 统一service接口服务,可一个文件一个接口
先从项目内部的文件划分说起,通常最为常见的情况是,很多开发人员都喜欢把很多很多很多接口都塞到一个接口文件里面。
这样的文件,通常会有2K到3K左右。我觉得这是一种极端,而且是一种不好的极端。因为文件过大的话,会带来很多问题。
但与之对立的有另一种做法,即一个文件,一个接口。这一点,在我之前就职的一家出名的游戏公司中得到了广泛的认可和遵循。如:
//?service=UserInfo.Go
class&Api_UserInfo&extends&PhalApi_Api&{
&&&&&public&function&go()&{
&&&&&&&&&&&//TODO
//?service=GroupInfo.Go
class&Api_GroupInfo&extends&PhalApi_Api&{
&&&&&public&function&go()&{
&&&&&&&&&&&//TODO
虽然也是一种极端,但却很好地做到了接口隔离,即不用担心修改此接口的实现而影响到其他接口服务。
最后,我们再来聊URL规则,就更顺畅了。如果我们采用一个文件对应一个接口,则我们可以省略Action(全部都为go()方法),简写成:?service=XXX。再进一步,我们可以利用接口服务器(如Nginx)的规则Rewrite来提供更好的URL规则,同时尽量隐藏我们的接口内部实现细节,如:
/?service=UserInfo.Go
/?service=UserInfo
//再进一步
/UserInfo.json
还有一点需要关注的就是接口的版本,当有v1,v2,v3等不同的版本时,我们也需要在接口URL中体现这些版本的不同。
主流的做法
新浪微博的一个接口URL:
优酷平台的一个接口URL:
微信的一个接口URL:
PhalApi的做法
目前而方,PhalApi在URL规则和路由这块还比较欠缺,没有像其他网站一样提供强大的路由支持。但我们在代码实现的层面,可以提供不同的入口,以开放给不同的终端(内部的或者外部的), 以及不同的版本支持。如:
$&tree&Public/
│&&&└──&index.php
│&&&└──&index.php
&&&&└──&index.php
3&directories,&3&files
则对应的版本URL则可以为:
/v1/?service=Default.Index
/v1/?service=Default.Index
/v1/?service=Default.Index
项目的选取
项目可以结合不同的入口,以及接口服务器的URL规则Rewrite作一些自定的URL路由。
(9)SDK包 - 给客户端自由的调用空间和自由
目前移动开发主要有iOS、Android、Windowns Phone、网站等不同的终端,各种终端又有不同的语言,如果我们需要提供SDK包,不仅仅需要考虑到纵向的版本升级,还需要维护横向的多样性。而且,如果我们使用的是HTTP协议,则不必要担心这些维护的成本,同时给客户端提供一个自由的空间进行调用 -- 即客户端可以自己编写本身的接口客户端。
主流的做法
很多国内的开放平台接口都是不提供SDK包的,但有些安全度高的则会,如支持宝。
以下是一些提供了SDK的平台 :
PhalApi的做法
我们暂时没有提供SDK包,但对于PHP,有一个简单的客户端类,可见:
项目的选取
出于公司产品簇的项目考虑,项目可以内部提供SDK给同类的客户端使用,如分为iOS版的客户端SDK,以及Android版的客户端SDK。
小故事:与SDK包的一个真实的痛苦经历
有一点是非常重要的,千万不要让不懂PHP语言的人去开发提供PHP的SDK包,更不要使用所谓的工具自动转换生成SDK包代码。在我曾经做过的一个项目中,因为需要接入一个接口系统,而这个接口是由专业的JAVA团队维护的,但他们对PHP语言则是非常薄弱,以致他们使用了工具来生成PHP语言的SDK包。
这就导致了我在接入一个简单的接口时,却开发联调耗费了两天、测试联调时耗费了在接口调用超时问题排查上。而最后找到的原因却是因为app_key不对而导致服务端异常,而在SDK包却隐藏了这一异常错误信息,反而给出了time out超时的提示,严重误导了排查的方向!而当我尝试深入去调试SDK时,得到却又是既没有code又没有message的异常!最让人难以忍受的是,他们提供的SDK包竟然和JAVA的企业系统一样复杂的结构(正如他们是使用工具来生成转换的)!
想象一下,PHP代码下有\com\sina\webo\sdk\Constants.php这样类似JAVA的文件结构,PHP的同学会作何感想?用JAVA的世界的方式来开发PHP,显然是走不通的啊!而执意要走的话,到最后就是各种接入的痛苦,稍微按奈不住的同学难免就会因为情绪问题而大开争论了。而这一切,只是因为非PHP人员使用了自动生成工具。我觉得,这是一种不负责任的做法,希望大家不要效仿。
(10)接口文档 - 使用markdown快速编写
(场外音:通过沐浴法理清了头绪,继续回来执笔编写)。就我个人经历而言,markdown就是一个开始你会拒绝,接着你会越来越喜欢,到最后会爱不释手的一个工具。
如果你或者你的团队还在使用邮件或者work文档来传递共享接口文档,那就太不应该了;如果你正在使用某个WIKI系统进行文档的维护但却不喜欢它的编辑或者展示方式时,你可以尝试使用一下markdown。正如你现在正在查看的文档也是通过markdown编写的。
主流的做法
作为开放接口平台,文档肯定是以网站的形式提供。但很多时候,对于我们内部的接口或者小项目来说,显然这样的成本太大了。接口,从简单开始。我们理应一直坚持这一点,所以文档也是一样,我们应该寻求一种在内部快速共享最新接口文档的途径。如:
1、使用内部WIKI
2、使用开源中国或者其他站点的WIKI(这时可以通过在线编辑或者GIT更新)
项目的选取
你可以根据项目的需要,或者公司以往的做法,但至少不要再使用邮件或者word文档。
(11)测试驱动开发 - 坚持单元测试
单元测试,在PhalApi里面不只一次提到了,这里再次进行说明,是希望能引起大家的关注,去尝试体验一下。
我们都知道,在开发一个新功能时、新接口时,修复一个BUG或者作一些大的调整或者重构工作,我们是毫无压力的,而且这时的成本很低,仅在于开发人员本身的时间和精力的消耗。当提测后进入测试阶段,测试人员发现一个BUG后,有些团队会以禅道或者Bugzilla或其他方式来纪录和追踪BUG。这时我们开发会觉得一个这么小的问题还需要去纪录、去登记很不值得。然后,我们应当注意到这时修复一个BUG会涉及到测试人员资源的开销。当进入了回归测试阶段,特别是多系统交互、跨团队合作时,一个BUG就会从一个人传到另一个人,从这个团队流到那个团队,这时成本就会逐渐增大。
最后,上线后,当一个奇怪的问题出现后,我们需要定位原因就更加困难重重了。我曾经就经历这样一番:有用户发现游戏的道具减少了。我们一开始以为是某些运营配置、或者数据以及用户的等级限制所引发的,但在排除了各种业务的问题后,到最后却发现是PHP中array使用“+”运算而引发的血案!在正常情况下,我们都知道array_merge()函数对于数值的下标则会追加并重新生成下标序列,即会合并;而数组+则会去掉相同下标的元素。
但实际情况下,线上BUG所产生的影响不在于排查和修复的时间成本,而在于在这段时间内所损失的金额、数据等成本。
当然,从测试的角度上看,测试并不能保证我们的系统没有BUG,只能说暂时未发现BUG。单元测试也一样,作为开发人员,我们应当在最低成本的时期就及时发现我们直觉觉得可能会出现的问题并进行修复。对我们亲手所编写的代码负责,并且用客观的方式来证明我们的代码目前未发现问题,而不是主观认为“我写的代码没有问题”。更不应该一次又一次地犯下各种低级或者重复的错误,而让团队其他成员对我们丧失信任。
PhalApi一直很注重单元测试,也很注重自动化,为了减轻大家重复编写单元测试骨架代码的痛苦,我们提供了一个可以生成单元测试代码的脚本。假设我们有这么一个类:
class&Api_Default&extends&PhalApi_Api&{
&&&&&&&&public&function&index()&{
&&&&&&&&&&&&&//TODO
那么,我们可以这样生成测试代码:
$&cd&.//Demo/Tests
$&phalapi-buildtest&../Api/Default.php&Api_Default&./test_env.php&
&*&PhpUnderControl_ApiDefault_Test
&*&针对&../Api/Default.php&Api_Default&类的PHPUnit单元测试
&*&@author:&dogstar&
require_once&dirname(__FILE__)&.&‘/test_env.php‘;
if&(!class_exists(‘Api_Default‘))&{
&&&&require&dirname(__FILE__)&.&‘/../Api/Default.php‘;
class&PhpUnderControl_ApiDefault_Test&extends&PHPUnit_Framework_TestCase
&&&&public&$apiD
&&&&protected&function&setUp()
&&&&&&&&parent::setUp();
&&&&&&&&$this-&apiDefault&=&new&Api_Default();
&&&&protected&function&tearDown()
&&&&&*&@group&testGetRules
&&&&public&function&testGetRules()
&&&&&&&&$rs&=&$this-&apiDefault-&getRules();
&&&&&*&@group&testIndex
&&&&public&function&testIndex()
&&&&&&&&$rs&=&$this-&apiDefault-&index();
温馨提示:
可以先执行:ln -s /path/to/PhalApi/phalapi-buildtest /usr/bin/phalapi-buildtest
test_env.php为测试环境初始化文件,可以在里面引用init.php文件,并作一些调整
输出的测试代码可以重定向到./Demo/Tests/Api/Api_Default_Test.php,让测试代码与产品代码对齐
最后,我们就可以这样执行单元测试了:
$&phpunit&./Api_Default_Test.php
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!|  
|  
|  
|  
|  
抱歉,指定的主题不存在或已被删除或正在被审核
Powered by& 痛苦头骨到底好在哪儿?
查看: 6965|回复: 12
UID1084905主题阅读权限30帖子精华0积分213金钱5290 荣誉1 人气21 在线时间2017 小时评议0
Lv.3游侠中级会员, 积分 213, 距离下一级还需 287 积分
帖子精华0积分213金钱5290 荣誉1 人气21 评议0
在论坛里泡了一段时间,发现大家都在说痛苦头骨是个好东西,可是好在哪儿呢?
1、是因为它的怒值+50%么?
2、法术力量100%是什么意思呢?
3、它怎么变成死亡头骨呢?
UID1874837主题阅读权限20帖子精华0积分149金钱474 荣誉1 人气0 在线时间11 小时评议0
Lv.2游侠会员, 积分 149, 距离下一级还需 51 积分
帖子精华0积分149金钱474 荣誉1 人气0 评议0
回复 #1 kenjicn 的帖子
不是,是升到死亡头骨时攻击+5,知识+5时的价值高。
带在身上打架,把100%磨到0就可以使用变死亡头骨了。
(ps:期间的痛苦,用过的人都知道,不然怎么叫痛苦头骨呢,还好怒加的快,顺便练怒灵了)
UID1084905主题阅读权限30帖子精华0积分213金钱5290 荣誉1 人气21 在线时间2017 小时评议0
Lv.3游侠中级会员, 积分 213, 距离下一级还需 287 积分
帖子精华0积分213金钱5290 荣誉1 人气21 评议0
回复 #2 sainny 的帖子
原来如此,我还以为看重它怒值+50%的特点呢,那是每一仗减1%么?
UID2211939主题阅读权限20帖子精华0积分11金钱147 荣誉0 人气0 在线时间15 小时评议0
Lv.2游侠会员, 积分 11, 距离下一级还需 189 积分
帖子精华0积分11金钱147 荣誉0 人气0 评议0
每一次战斗好像减1%-4%不等。越早结束战斗好像减的越多~
UID1469990主题阅读权限20帖子精华0积分77金钱343 荣誉0 人气0 在线时间6 小时评议0
头像被屏蔽
帖子精华0积分77金钱343 荣誉0 人气0 评议0
提示: 作者被禁止或删除 内容自动屏蔽
UID1084905主题阅读权限30帖子精华0积分213金钱5290 荣誉1 人气21 在线时间2017 小时评议0
Lv.3游侠中级会员, 积分 213, 距离下一级还需 287 积分
帖子精华0积分213金钱5290 荣誉1 人气21 评议0
到了精灵大陆才捡宝箱捡到的头骨,现在回前几个大陆去打扫一下,实力已经不成比例了,魔法值减半就减半吧,100%一会儿就过了啊
UID3165232主题阅读权限10帖子精华0积分2金钱44 荣誉0 人气0 在线时间1 小时评议0
Lv.1游侠新人, 积分 2, 距离下一级还需 3 积分
帖子精华0积分2金钱44 荣誉0 人气0 评议0
刚玩法师史诗打完幽灵城堡才出,好痛苦啊,到龙迷宫才升级好
UID946648主题阅读权限20帖子精华0积分49金钱226 荣誉0 人气0 在线时间22 小时评议0
Lv.2游侠会员, 积分 49, 距离下一级还需 151 积分
帖子精华0积分49金钱226 荣誉0 人气0 评议0
我晕。。看到了一直没带啊。。。以为垃圾。。。这个狂怒50%是作战时流入+50吗???还是我作战时的狂怒值+50%啊?
游戏中还有哪些装备是升级后才厉害的啊?
UID2315258主题阅读权限20帖子精华0积分42金钱342 荣誉0 人气0 在线时间52 小时评议0
Lv.2游侠会员, 积分 42, 距离下一级还需 158 积分
帖子精华0积分42金钱342 荣誉0 人气0 评议0
基本上能升级的装备都升级后才厉害
UID3844170主题阅读权限20帖子精华0积分36金钱122 荣誉0 人气0 在线时间1 小时评议0
Lv.2游侠会员, 积分 36, 距离下一级还需 164 积分
帖子精华0积分36金钱122 荣誉0 人气0 评议0
升级之前是次品,升级之后是极品,几乎所有角色都好用
UID4022120主题阅读权限40帖子精华0积分534金钱788 荣誉0 人气0 在线时间82 小时评议0
Lv.4游侠高级会员, 积分 534, 距离下一级还需 466 积分
帖子精华0积分534金钱788 荣誉0 人气0 评议0
升级的过程是“痛苦”的,不然干嘛它叫做“痛苦”头骨呢?
实际效果是打仗的时候发现自己的魔法值减半了,本来能放大招的开仗不能放了。
反过来说,战士其实练这个家伙比法师要好受些,法师对魔法的依赖程度高些。战士应该以怒值说话。
这个东西越早入手越好,否则后期练它别扭,不练它更别扭。
CPU&&Core 2 Duo E7400 oc @ 3.5GHz
主板 七彩虹 Intel G31H V2.3
内存 金世顿 DDR2 400 2GBX2
显卡 Inno 3D GTX 260+ 216sp
硬盘 WD 7200转 160G 8M
显示器 19“Philips HDCP
电源 海盗船 VX550W
UID3919704主题阅读权限40帖子精华2积分724金钱2191 荣誉6 人气33 在线时间1940 小时评议0
Lv.4游侠高级会员, 积分 724, 距离下一级还需 276 积分
帖子精华2积分724金钱2191 荣誉6 人气33 评议0
原帖由 DRWilson 于
16:43 发表
升级的过程是“痛苦”的,不然干嘛它叫做“痛苦”头骨呢?
实际效果是打仗的时候发现自己的魔法值减半了,本来能放大招的开仗不能放了。
反过来说,战士其实练这个家伙比法师要好受些,法师对魔法的依赖程度高些。战士应该以 ...
我玩法师的时候,前面都特意留一些小怪不杀,留着升痛苦头骨,如果是史诗难度,魔法减半,本来怪就强到让人恶心,魔法减半......还咋打..
天邈汉化组翻译【资深】
UID2386769主题阅读权限40帖子精华2积分870金钱2768 荣誉32 人气0 在线时间6 小时评议0
Lv.4游侠高级会员, 积分 870, 距离下一级还需 130 积分
帖子精华2积分870金钱2768 荣誉32 人气0 评议0
练完完全可以不升级
到0%了就不会再扣一半MP
毕竟是50%怒值流入啊……
Powered by

我要回帖

更多关于 紫钻什么时候升级 的文章

 

随机推荐